可能是顺序表研究的细致了一点,单链表操作一下子就实现了。这里先实现带头结点的单链表操作。

大概有以下知识点.

1;结点:结点就是单链表中研究的数据元素,结点中存储数据的部分称为数据域,存储直接后继地址的部分称为指针域。

2;结点示意图:

3;头指针:头指针始终指向链表第一个元素,当有头结点时头结点就是链表第一个元素。头指针具有标识左右,故头指针命名为链表的名字,这里为linklist。头指针是一定存在的。

4;头结点:引入头结点的目的是,将链表首元结点的插入和删除操作与其他结点的插入和删除操作统一起来。(即头指针地址不在发生变化)

5;单链表结点结构体表示:

1 struct LNode
2 {
3 int data; //姑且认为其数据为整型
4 struct LNode * next;
5 };
6
7 typedef struct LNode * linklist

6;单链表的操作集合,头文件 defs.h

 1 #ifndef _DEFS_H_
2 #define _DEFS_H_
3
4 #include<stdio.h>
5 #include<stdlib.h>
6 #include<malloc.h>
7
8 struct LNode //单链表结点的定义
9 {
10 int data;
11 struct LNode * next;
12 }
13 typedef struct LNode * linklist
14
15 //操作集合
16 void InitList(linklist *L); //申请头结点,头指针地址改变
17 void DestroyList(linklist *L); //须释放头结点,头指针地址改变
18 void ClearList(linklist L); //保留头结点,头指针地址不变
19 void ListEmpty(linklist L);
20 int ListLength(linklist L);
21 int GetElem(linklist L, int i, int *e);
22 int LocateElem(linklist L, int e);
23 int PriorElem(linklist L, int cur_e, int *pri_e);
24 int NextElem(linklist L, int cur_e, int *nex_e);
25 int ListInsert(linklist L, int i, int e); //插入不改变头指针的值
26 int ListDelete(linklist L, int i, int *e); //删除操作也不改变头指针的值
27 void TravelList(linklist L);
28 #endif

7;InitList操作实现

 1 #include"defs.h"
2
3 void InitList(linklist *L) //接受头指针的地址值
4 {
5 *L = (linklist)malloc(sizeof(struct LNode)); //*L表示头指针
6
7 if (*L == NULL)
8 {
9 printf("分配结点失败。\n");
10 exit(-1);
11 }
12 (*L)->next = NULL; //置头结点的next域为空
13 }

InitList.c

8;DestroyList操作的实现

 1 #include"defs.h"
2
3 void DestroyList(linklist *L) //接受的参数为头指针的地址值
4 {
5 linklist p ;
6 while (*L)
7 {
8 p = (*L)->next; //释放结点之前先保存结点的下一个地址,防止线索被断
9 free(*L);
10 *L = p; //将下一个结点,作为释放结点
11 }
12 }

DestroyList.c

9;ClearList操作的实现

 1 #include"defs.h"
2
3 void ClearList(linklist L) //保留头结点
4 {
5 linklist p = L->next; //p将头指针的next值保存起来,p指向首元结点
6 L->next = NULL;
7
8 DestroyList(&p); //调用撤销函数,释放后面的结点
9
10 }

ClearList.c

10;ListEmpty操作的实现

1 #include"defs.h"
2
3 void ListEmpty(linklist L)
4 {
5 if (L->next == NULL) //判断头结点指针域是否为空
6 printf("链表为空.\n");
7 else
8 printf("链表不为空.\n");
9 }

ListEmpty.c

11;ListLength操作实现

 1 #include"defs.h"
2
3 int ListLength(linklist L)
4 {
5 int j=0; //作为计数器
6 linklist p = L->next; //p指向首元结点,作为移动指针
7
8 while (p) //从首元结点开始
9 {
10 ++j;
11 p = p->next;
12 }
13 return j;
14 }

ListLength.c

12;GetElem操作实现

 1 #include"defs.h"
2
3 int GetElem(linklist L, int i, int *e) // 1<= i <=ListLength(L)
4 {
5 int j = 0; //j作为计数器
6 linklist p = L;
7
8 while (p && j<i) //找到第i个结点
9 {
10 ++j;
11 p = p->next;
12 }
13 if (!p || i<1) //取值位置不合理
14 exit(0);
15
16 *e = p->data;
17 return 0;
18 }

GetElem.c

13;LocateElem操作实现

 1 #include"defs.h"
2
3 int LocateElem(linklist L, int e)
4 {
5 linklist p = L->next; //p作为移动指针,p指向第一个元素
6 int j = 0; //j作为计数器
7
8 while (p)
9 {
10 ++j;
11 if (p->data == e)
12 return j;
13 p = p->next;
14 }
15 return 0;
16 }

LocateElem.c

14;PriorElem操作实现

 1 #include"defs.h"
2
3 int PriorElem(linklist L, int cur_e, int *pri_e) //第一个元素无前驱
4 {
5 linklist p = L->next; //p指向首元结点
6 linklist q;
7
8 while (p)
9 {
10 q = p->next; //q为p的后继
11
12 if (q && q->data == cur_e) //则p就是q的前驱
13 *pri_e = p->data;
14 p = q; //循环
15 }
16 return 0;
17 }

PriorElem.c

15;NextElem操作的实现

 1 #include"defs.h"
2
3 int NextElem(linklist L, int cur_e, int *nex_e) //最后一个元素无后继
4 {
5 linklist p = L->next; //p指向首元结点
6 linklist q;
7
8 while (p)
9 {
10 q = p->next; //q为p的后继
11
12 if (q && p->data == cur_e) //p有后继,且p的数据域与当前值相等
13 *nex_e = q->data;
14 p = q; //更新p
15 }
16 return 0;
17 }

NextElem.c

16;ListInsert操作的实现

 1 #include"defs.h"
2
3 int ListInsert(linklist L, int i, int e) //1<= i <= ListLength(L)
4 {
5 int j=0; //j为基数器
6 linklist p = L; //p为移动指针,p指向头结点
7 linklist q, s;
8
9 while (p && j<i-1) //找到第i-1个结点
10 {
11 ++j;
12 p = p->next;
13 }
14
15 if (!p || i<1) //插入位置不合理
16 return 0;
17
18 q = p->next; //q指向第i个结点
19
20 s = (linklist)malloc(sizeof(struct LNode));
21 if (!s) //分配失败
22 exit(-1);
23
24 s->data = e; //置s的数据域为e
25 s->next = q; //插入操作,是指针连起来
26 p->next = s;
27 return 0;
28 }

ListInsert.c

17;ListDelete操作的实现

 1 #include"defs.h"
2
3 int ListDelete(linklist L, int i, int *e) // 1<= i <=ListLength(L)
4 {
5 int j = 0; //j为计数器
6 linklist p = L;
7 linklist q;
8
9 while (p && j<i-1) //找到第i-1个结点
10 {
11 ++j;
12 p = p->next;
13 }
14
15 if (!p || i<1) //删除位置不合理
16 exit(0);
17 q = p->next; //q指向第i个结点
18
19 *e = q->data; //先将第i个结点的数据域带出
20 p->next = q->next; //连起指针
21 free(q); //释放第i个结点
22
23 return 0;
24 }

ListDelete.c

18;TravelList操作实现

 1 #include"defs.h"
2
3 void TravelList(linklist L)
4 {
5 linklist p = L->next; //p指向首元结点
6 int j = 0; //j为计数器
7
8 while (p)
9 {
10 ++j;
11 printf("第%d个结点的数据域的值为:%d\n", j, p->data);
12 p = p->next; //更新p
13 }
14 }

TravelList.c

19;makefile的实现,其代码与顺序表的一样,这里换成另一种写法

 1 object = main.o InitList.o DestroyList.o ClearList.o ListEmpty.o \
2 ListLength.o GetElem.o LocateElem.o PriorElem.o NextElem.o \
3 ListInsert.o ListDelete.o TravelList.o
4
5 test : $(object)
6 gcc -g -Wall -o test $(object)
7
8 $(object) : defs.h
9
10 .PHONY : clean
11 clean :
12 rm -f *.o

20;顺序表与单链表的比较

顺序表是用一段地址连续的存储单元来存放数据元素,适合查找,不适合频繁插入和删除(没一次操作都是O(n));

单链表是用不连续的存储单元,其数据元素之间是用指针来连接,每一次的查找都必须通过头指针来遍历,因此其不适合频繁的查找。但是对于插入和删除操作,它不需要移动其它元素,算法时间复杂度为O(1),因此特别适合频繁的插入和删除操作。

c语言实现--带头结点单链表操作的更多相关文章

  1. 数据结构之 线性表---单链表操作A (删除链表中的指定元素)

    数据结构上机测试2-1:单链表操作A Time Limit: 1000MS Memory limit: 4096K 题目描述 输入n个整数,先按照数据输入的顺序建立一个带头结点的单链表,再输入一个数据 ...

  2. Java带头节点单链表的增删合并以及是否有环

    带头节点单链表 1.优势: 1)当链表为空时,指针指向头结点,不会发生null指针异常 2)方便特殊操作(删除第一个有效节点或者插入一个节点在表头) 3)单链表加上头结点之后,无论单链表是否为空,头指 ...

  3. 单链表操作B 分类: 链表 2015-06-07 12:42 15人阅读 评论(0) 收藏

    数据结构上机测试2-2:单链表操作B TimeLimit: 1000ms Memory limit: 65536K 题目描述 按照数据输入的相反顺序(逆位序)建立一个单链表,并将单链表中重复的元素删除 ...

  4. c语言实现--不带头结点的单链表操作

    1,不带头结点的单链表操作中,除了InitList(),GetElem(),ListInsert(),ListDelete()操作与带头结点的单链表有差别外,其它的操作基本上一样. 2,不带头结点单链 ...

  5. C语言,单链表操作(增删改查)(version 0.1)

    这天要面试,提前把链表操作重新写了一遍.备份一下,以备不时之需. 希望有人能看到这篇代码,并指正. // File Name : list.h #include "stdafx.h" ...

  6. C单链表操作

    #include <stdio.h> #include <stdlib.h> #define ElemType int #define Status int #define O ...

  7. C++学习(三十五)(C语言部分)之 单链表

    单链表 就好比火车 火车头-->链表头部火车尾-->链表尾部火车厢-->链表的节点火车厢连接的部分-->指针火车中的内容-->链表节点的的数据链表节点包含数据域和指针域数 ...

  8. C语言版本:循环单链表的实现

    SClist.h #ifndef __SCLIST_H__ #define __SCLIST_H__ #include<cstdio> #include<malloc.h> # ...

  9. C++ 单链表操作总结

    第一.单链表的定义和操作 #include <iostream> using namespace std; template <typename T> struct Node ...

随机推荐

  1. C#中的异步和多线程

    许多开发人员对异步代码和多线程以及它们的工作原理和使用方法都有错误的认识.在这里,你将了解这两个概念之间的区别,并使用c#实现它们. 我:"服务员,这是我第一次来这家餐厅.通常需要4个小时才 ...

  2. Hash Tables and Hash Functions

    Reference: Compuer science Introduction: This computer science video describes the fundamental princ ...

  3. AttGAN: Facial Attribute Editing by Only Changing What You Want 论文阅读笔记和AttGan的pytorch代码实现

    1.总体框架 上面的过程用详细描述即是 Test阶段: Train阶段: 由于我们无法得知编辑后的image,所以显而易见人脸属性编辑是一个无监督问题,而对于我们的xa需要获得关于b的属性,故利用at ...

  4. 四:WEB源码扩展

    前言:WEB源码在安全测试中是非常重要的信息来源,可以用来进行代码审计漏洞也可以用来做信息突破口,其中WEB源码有很多技术需要简明分析,获取某ASP源码后就可以采用默认数据库下载为突破,获取某其他脚本 ...

  5. P2024 [NOI2001]食物链(种类并查集)

    题目链接: https://www.luogu.org/problemnew/show/P2024 题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 ...

  6. 关于阿里云服务器安装了Apache开放80端口访问不了网页

    先用netstat -tlunp查看80端口是否打开,再关闭服务器的防火墙,可以用 systemctl status firewalld 查看防火墙状态  systemctl stop firewal ...

  7. Jenkins 部署打包文件 并通过SSH上传到 linux服务器

    编译 发布 打包成zip文件 dotnet clean : dotnet的命令清除解决方案 dotnet build : dotnet的命令重新生成 dotnet publish .\Hy.MyDem ...

  8. 消息队列之rabbitmq学习使用

    消息队列之rabbitmq学习使用 1.RabbitMQ简介 1.1.什么是RabbitMQ? RabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据,Rabb ...

  9. 网络编程 — Linux TCP服务端和客户端

    1. 服务端 #include <stdlib.h> #include <string.h> #include <errno.h> #include <sig ...

  10. 一键测试VPS到国内速度脚本 SuperBench.sh,以及一键验收云主机脚本

    我们买国外VPS服务器测试网络通常会用到speedtest,speedtest默认是测试到最近的节点,那么到国内速度如何呢?虽然可以指定服务器编号,但是一个个测试还是比较麻烦的,这里推荐一个脚本整合了 ...