@


单链表

结构定义

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h> #define OK 1
#define ERROR 0
#define OVERFLOW -1
#define YES 1
#define NO 0 typedef int ElemType;
typedef int Status; #pragma warning(disable:4996) /*
单链表的存储结构定义
*/
typedef struct Node
{
ElemType data; // 数据域
struct Node* next; // 指针域
}LinkNode, * LinkList;
// *LinkList为LinkNode类型的指针
// 定义指向结点的指针: LinkNode *p 等价于 LinkList p

初始化

/*
初始化(构造一个带头结点空表)
*/
Status InitList(LinkList* L)
{
*L = (LinkNode*)malloc(sizeof(LinkNode));
(*L)->next = NULL; return OK;
}

建立

前插法

/*
单链表的建立(前插法)
*/
void CreateList_Head(LinkList L, int n)
{
ElemType e; for (int i = 0; i < n; i++) {
LinkNode* p = (LinkNode*)malloc(sizeof(LinkNode)); // 生成新结点
scanf("%d", &e);
p->data = e; // 输入元素值
p->next = L->next;
L->next = p; // 插入到表头
}
}

尾插法

/*
单链表的建立(尾插法)
*/
void CreateList_Rear(LinkList L, int n)
{
ElemType e; LinkList r = L; // 尾指针r指向头结点
for (int i = 0; i < n; i++) {
LinkNode* p = (LinkNode*)malloc(sizeof(LinkNode)); // 生成新结点
scanf("%d", &e); // 输入元素值
p->data = e;
p->next = NULL;
r->next = p; // 插入到表尾
r = p; // r指向新的尾结点
}
}

清空

/*
清空,将L重置为空表
*/
Status ClearList(LinkList L)
{
LinkNode* p;
LinkNode* q;
p = L->next; // p指向第一个结点 while (p) // 没到表尾
{
q = p->next;
free(p);
p = q;
}
L->next = NULL; // 头结点指针域为空 return OK;
}

求表长

/*
求表长,返回L中数据元素个数
*/
int GetListLength(LinkList L)
{
LinkNode* p = L->next; // p指向第一个结点
int len = 0; // 遍历单链表,统计结点数
while (p) {
len++;
p = p->next;
} return len;
}

判断是否为空表

/*
判断表是否为空
*/
Status IsListEmpty(LinkList L)
{
// 若L为空表,则返回YES,否则返回NO
if (L->next) // 非空
return NO;
else
return YES;
}

取值

/*
取值(根据位置i获取相应位置数据元素的内容,0<i<=len)
*/
Status GetElem(LinkList L, int i, ElemType* e)
{
LinkNode* p = L->next;
int j = 1; // 初始化 // 向后扫描,直到p指向第i个元素或p为空
while (p && j < i) {
p = p->next;
j++;
} if (!p || j > i) {
return ERROR; // 第i个元素不存在
} (*e) = p->data; // 若存在,取第i个元素 return OK;
}

查找

获取数据所在位置

/*
查找(根据指定数据,获取数据所在位置)
*/
LinkNode* LocateELem(LinkList L, ElemType e)
{
// 返回L中值为e的数据元素的地址,查找失败返回NULL
LinkNode* p = L->next; while (p && p->data != e) {
p = p->next;
} return p;
}

获取数据所在位序

/*
查找(根据指定元素,返回指定元素位序,0<序号<=len)
*/
int SearchElem(LinkList L, ElemType e)
{
// 返回L中值为e的数据元素的位置序号,查找失败返回0
LinkNode* p = L->next;
int j = 1; while (p && p->data != e)
{
p = p->next; j++;
} if (p) {
return j;
}
else {
return 0;
}
}

插入

/*
插入,将元素插入到指定位序(插在第 i 个结点之前,0<i<=len+1)
*/
Status InsertElem(LinkList L, int i, ElemType e)
{
LinkList p = L;
int j = 0; // 寻找第i-1个结点
while (p && j < i - 1) {
p = p->next;
j++;
} if (!p || j > i - 1) {
return ERROR; // i大于表长 + 1或者小于1
} LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode)); //生成新结点s
s->data = e; // 将结点s的数据域置为e
s->next = p->next; // 将结点s插入L中
p->next = s; return OK;
}

删除

/*
删除(删除第 i 个结点)
*/
Status DeleteElem(LinkList L, int i, ElemType* e)
{
LinkList p = L;
int j = 0; // 寻找第i个结点,并令p指向其前驱
while (p->next && j < i - 1) {
p = p->next;
j++;
} if (!(p->next) || j > i - 1) {
return ERROR; // 删除位置不合理
} LinkNode* q = p->next; // 临时保存被删结点的地址以备释放
p->next = q->next; // 改变删除结点前驱结点的指针域
(*e) = q->data; // 保存删除结点的数据域
free(q); // 释放删除结点的空间 return OK;
}

销毁

/*
销毁
*/
Status DestroyList(LinkList L)
{
LinkList p;
while (L)
{
p = L;
L = L->next;
free(p);
} return OK;
}

遍历打印

/*
遍历打印链表
*/
void PrintLinkList(LinkList L)
{
LinkNode* p = L->next; while (p)
{
printf("%d", p->data);
p = p->next;
if (p) {
printf(" ");
}
}
}

测试

int main() {
// 测试数据:1 32 80 60 44 7 9 10
LinkList L; Status a1 = InitList(&L);
printf("初始化:\na1 = %d\n", a1); printf("\n头插法:");
CreateList_Head(L, 8);
printf("链表打印:");
PrintLinkList(L); Status a2 = ClearList(L);
printf("\n\n清空链表:a2 = %d\n", a2);
printf("链表打印:");
PrintLinkList(L); printf("\n\n尾插法:");
CreateList_Rear(L, 8);
printf("链表打印:");
PrintLinkList(L); printf("\n\n求表长:");
int len1 = GetListLength(L);
printf("\nlen1 = %d\n", len1); printf("\n判断是否为空:\n");
Status a3 = IsListEmpty(L);
printf("a3 = %d\n", a3); printf("\n取值:\n");
ElemType e1;
Status a4 = GetElem(L, 9, &e1);
printf("a4 = %d, e1 = %d\n", a4, e1);
a4 = GetElem(L, 1, &e1);
printf("a4 = %d, e1 = %d\n", a4, e1);
a4 = GetElem(L, 3, &e1);
printf("a4 = %d, e1 = %d\n", a4, e1);
a4 = GetElem(L, 8, &e1);
printf("a4 = %d, e1 = %d\n", a4, e1); printf("\n查询元素地址:\n");
ElemType e2 = 1;
LinkNode* p1 = LocateELem(L, e2);
printf("p1 = %p, p1->data = %d\n", p1, p1->data);
ElemType e3 = 6;
LinkNode* p2 = LocateELem(L, e3);
printf("p2 = %p\n", p2);
ElemType e4 = 10;
LinkNode* p3 = LocateELem(L, e4);
printf("p3 = %p, p3->data = %d\n", p3, p3->data); printf("\n查询元素序号:\n");
int a5 = SearchElem(L, e2);
printf("a5 = %d\n", a5);
int a6 = SearchElem(L, e3);
printf("a6 = %d\n", a6);
int a7 = SearchElem(L, e4);
printf("a7 = %d\n", a7); printf("\n插入元素:\n");
Status a8 = InsertElem(L, 9, 99);
printf("a8 = %d\n", a8);
printf("链表打印:");
PrintLinkList(L);
a8 = InsertElem(L, 1, 11);
printf("\na8 = %d\n", a8);
printf("链表打印:");
PrintLinkList(L); printf("\n\n删除元素:\n");
ElemType e5;
Status a9 = DeleteElem(L, 3, &e5);
printf("链表打印:");
PrintLinkList(L); printf("\n\n销毁链表:");
Status a10 = DestroyList(L);
printf("\n%p", L);
printf("\n%p", L->next); return 0;
}

测试结果:

《数据结构-C语言》单链表的更多相关文章

  1. C语言单链表实现19个功能完全详解

    谢谢Lee.Kevin分享了这篇文章 最近在复习数据结构,想把数据结构里面涉及的都自己实现一下,完全是用C语言实现的. 自己编写的不是很好,大家可以参考,有错误希望帮忙指正,现在正处于编写阶段,一共将 ...

  2. js数据结构与算法--单链表的实现与应用思考

    链表是动态的数据结构,它的每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成. 现实中,有一些链表的例子. 第一个就是寻宝的游戏.你有一条线索,这条线索是指向寻找下一条线 ...

  3. 数据结构——Java实现单链表

    一.分析 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素.链表中的数据是以结点来表示的,每个结点由元素和指针构成.在Java中,我们可以将单链表定义成一个类,单链表的基 ...

  4. PHP数据结构之实现单链表

    学习PHP中,学习完语法,开始尝试实现数据结构,今天实现单链表 <?php class node //节点的数据结构 { public $id; public $name; public $ne ...

  5. C++ 数据结构学习二(单链表)

    模板类 //LinkList.h 单链表#ifndef LINK_LIST_HXX#define LINK_LIST_HXX#include <iostream>using namespa ...

  6. C语言—单链表

    单链表操作:读取,插入和删除 #include "stdafx.h" #include <string.h> #include <stdio.h> #inc ...

  7. C语言——单链表初始化、求表长、读表元素、插入元素

    头文件Linear.h // 单链表的类型定义 typedef struct node { int data; // 数据域 struct node *next; // 指针域 }Node, *Lin ...

  8. c语言-单链表(二)

    继续复习链表知识点,本章包含单链表的增加,删除,判断是否为空,和链表长度,以及链表的排序 几个知识点 1.链表的判断是否为空 //1.判断链表是否为空 bool isempty_list(PNODE ...

  9. c语言单链表实现

    /************************************************************************* > File Name: singleLin ...

  10. C语言单链表的实现

    // //  main.c //  gfhjhgdf // //  Created by chenhao on 13-12-23. //  Copyright (c) 2013年 chenhao. A ...

随机推荐

  1. ET介绍——CSharp协程

    什么是协程 说到协程,我们先了解什么是异步,异步简单说来就是,我要发起一个调用,但是这个被调用方(可能是其它线程,也可能是IO)出结果需要一段时间,我不想让这个调用阻塞住调用方的整个线程,因此传给被调 ...

  2. 文心一言 VS 讯飞星火 VS chatgpt (27)-- 算法导论5.1 2题

    二.请描述 RANDOM(a,b)过程的一种实现,它只调用 RANDOM(0,1).作为a和b的函数,你的过程的期望运行时间是多少? 文心一言: 假设我们有一个伪随机数生成器,可以生成在[0,1)范围 ...

  3. binfmt_misc

    一:binfmt_misc是什么 binfmt_misc是内核中的一个功能,它能将非本机的二进制文件与特定的解析器自动匹配起来,进行二进制解析. 例如,在x86上解析arm64架构的二进制. 通过bi ...

  4. C#里的var和dynamic区别到底是什么,你真的搞懂了嘛

    前言 这个var和dynamic都是不确定的初始化类型,但是这两个本质上的不同.不同在哪儿呢?var编译阶段确定类型,dynamic运行时阶段确定类型.这种说法对不对呢?本篇看下 概括 以下详细叙述下 ...

  5. 【HarmonyOS】一文教你如何在低代码项目中跳转H5页面

    ​ [关键字] 元服务.低代码.H5页面跳转.WebView [1.写在前面] 今天我们来实现一个在低代码项目中通过按钮跳转到H5页面的功能,本项目是基于API6的JS工程,我们的实现思路是在页面B中 ...

  6. CKS 考试题整理 (05)-Container 安全上下文

    Context Container Security Context 应在特定 namespace 中修改 Deployment. Task 按照如下要求修改 sec-ns 命名空间里的 Deploy ...

  7. @Override注解的使用

    先看看@Override注解在Java SE中的声明: package .lang; import java.lang.annotation.*; @Target(ElementType.METHOD ...

  8. Gamma:强大的AI制作PPT神器,用完再也回不去了!

    看过许多 AI 制作 PPT 软件,最终还是被 Gamma 惊艳到. Gamma 是一款基于人工智能技术的 PPT 制作工具,可以帮助用户轻松制作高质量的 PPT 演示文稿. 痛点解决 相比传统制作 ...

  9. macOS 系统 Kafka 快速入门

    Kafka 的核心功能是高性能的消息发送与高性能的消息消费.以下是 Kafka 的快速入门教程. 下载并解压缩 Kafka 二进制代码压缩文件 打开 Kafka 官网的下载地址,可以看到不同版本的 K ...

  10. 屏蔽CSDN百度广告

    最近在查询一些技术问题访问到CSDN时一直弹一些令人作恶的广告,说个特别的广告,脱发广告,特别有针对性程序员同胞们的共性问题,不过还是特别恶心,百度了一下,大家也特别反感,CSDN你真这么缺钱?废话不 ...