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

2,不带头结点单链表示意图:

链表指针直接指向了首元节点,因此在首元节点前插入数据元素或者删除首元节点元素都会改变头指针的值。

3,不带头结点的单链表定义及操作集合,除了插入,删除,清空操作需要传递头指针的地址外,基本上一样。头文件defs.h

 1 #ifndef _DEFS_H_
2 #define _DEFS_H_
3
4 #include<stdio.h>
5 #include<malloc.h> //malloc(),free()
6 #include<stdlib.h> //exit()
7
8 struct LNode
9 {
10 int data;
11 int * next;
12 };
13 typedef struct LNode * linklist;
14
15 //操作集合,注意ClearList,ListInsert,ListDelete
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 //只要是能够改变头指针的值,均是传递头指针的地址

4,InitList操作。其不需要分配结点,直接令头指针为空

1 #include"defs.h"
2
3 void InitList(linklist *L)
4 {
5 (*L) = NULL; //*L即表示头指针
6 }

InitList.c

5,DestroyList操作.其就是释放所有结点。

 1 #include"defs.h"
2
3 void DestroyList(linklist *L)
4 {
5 linklist p; //p为移动指针
6 while (*L)
7 {
8 p = (*L)->next; //释放某一结点时,需保存其下一个结点的地址
9 free(*L);
10 *L = p;
11 }
12 }

DesroyList.c

6,ClearList操作。其意思和撤销一样,释放所有结点.(带头结点的清空,保留了头结点)

 1 #include"defs.h"
2
3 void ClearList(linklist *L)
4 {
5 linklist p;
6 while (*L)
7 {
8 p = (*L)->next;
9 free(*L);
10 *L = p;
11 }
12 }

ClearList.c

7,ListEmpty操作.判断链表是否为空。

1 #include"defs.h"
2
3 void ListEmpty(linklist L)
4 {
5 if (L) //L不为空
6 printf("链表不为空。\n");
7 else
8 printf("链表为空.\n");
9 }

ListEmpty.c

8,ListLength操作。求链表的长度,需要从第一个结点开始遍历。

 1 #include"defs.h"
2
3 int ListLength(linklist L)
4 {
5 int j = 0; //作为计数器
6 linklist p = L;
7 while (p)
8 {
9 ++j;
10 p = p->next;
11 }
12 return j;
13 }

ListLength.c

9,GetElem操作。需要判断元素位置的合法性。

 1 #include"defs.h"
2
3 int GetElem(linklist L, int i, int *e)
4 {
5 int j = 1; //j记第一个结点开始
6 linklist p = L;
7
8 if (i<1) //位置不合法
9 exit(0);
10 while (p && j<i) //找到第i个结点
11 {
12 ++j;
13 p = p->next;
14 }
15 if (j==i && p) //判断第i个位置元素是否存在,同时也解决了i = 1的情况
16 *e = p->data;
17
18 return 0;
19 }

GetElem.c

10,LocateElem操作。需要从表一个结点遍历。查找成功返回其位置值,失败则返回-1

 1 #include"defs.h"
2
3 int LocateElem(linklist L, int e)
4 {
5 linklist p = L;
6 int j = 0;
7
8 while (p)
9 {
10 ++j;
11 if (p->data == e)
12 return j;
13 p = p->next; //更新p
14 }
15 return -1; //查找失败,返回-1
16 }

LocateElem.c

11,PriorElem操作。

 1 #include"defs.h"
2
3 int PriorElem(linklist L, int cur_e, int *pri_e)
4 {
5 linklist p = L;
6 linklist q;
7
8 while (p)
9 {
10 q = p->next; //q指向p的后继
11 if (q && q->data == cur_e) //q存在,且q的数据和当前值相等
12 {
13 *pri_e = p->data; //p即为q前驱
14 return 0;
15 }
16 p = q; //更新p
17 }
18
19 return 0;
20 }

PriorElem.c

12,NextElem操作。 求前驱与后继的操作,基本一样。两个指针。

 1 #include"defs.h"
2
3 int NextElem(linklist L, int cur_e, int *nex_e)
4 {
5 linklist p = L;
6 linklist q;
7
8 while (p)
9 {
10 q = p->next; //q指向p的后继
11 if (q && p->data == cur_e) //q存在且p的数据与当前值相等
12 {
13 *nex_e = q->data; //q即为p的后继
14 return 0;
15 }
16 p = q;
17 }
18 return 0;
19 }

NextElem.c

13,ListInsert操作。

 1 #include"defs.h"
2
3 int ListInsert(linklist *L, int i, int e)
4 {
5 int j = 1; //j从1开始计数
6 linklist p = *L;
7 linklist q, s;
8
9 if (i<1) //位置不合理
10 exit(0);
11
12 s = (linklist)malloc(sizeof(struct LNode));
13 s->data = e;
14
15 if (i==1)
16 {
17 s->next = p;
18 *L = s;
19 }
20 else
21 {
22 while (p && j<i-1) //找到第i-1个结点
23 {
24 ++j;
25 p = p->next;
26 }
27 if (p)
28 {
29 q = p->next; //q指向第i个结点,q可以为空
30 s->next = q;
31 p->next = s;
32 }
33 }
34 return 0;
35 }

ListInsert.c

14,ListDelete操作。

 1 #include"defs.h"
2
3 int ListDelete(linklist *L, int i, int *e)
4 {
5 int j = 1;
6 linklist p = *L;
7 linklist q;
8
9 if (*L == NULL) //链表为空
10 exit(0);
11 if (i==1)
12 {
13 q = p->next; //q指向p的后继,保存后一个地址
14 free(*L);
15 *L = q;
16 }
17 else
18 {
19 while (p && j<i-1) //找到第i-1个位置
20 {
21 ++j;
22 p = p->next;
23 }
24 q = p->next; //q指向第i个位置
25 if (!q || i<1) //第i个位置不存在
26 exit(0);
27 p->next = q->next; //p指向第i+1个位置
28 free(q); //释放第i个结点
29 }
30
31 }

ListDelete.c

15,TravelList操作。

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

TravelList.c

16,main.c测试代码里,初始插入时应该从第一个位置开始插入。(初始时为空表)
17,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

makefile

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

  1. java编写带头结点的单链表

    最近在牛客网上练习在线编程,希望自己坚持下去,每天都坚持下去练习,给自己一个沉淀,不多说了 我遇到了一个用java实现单链表的题目,就自己在做题中将单链表完善了一下,希望大家作为参考也熟悉一下,自己 ...

  2. C/C++中创建(带头结点、不带头结点的)单链表

    1.带头结点的单链表(推荐使用带头结点的单链表)(采用尾插法) 了解单链表中节点的构成 从上图可知,节点包含数据域和指针域,因此,在对节点进行定义时,我们可以如下简单形式地定义: /* 定义链表 */ ...

  3. 链表习题(2)-一个集合用带头结点的单链表L表示,编写算法删除其值最大的结点。

    /*一个集合用带头结点的单链表L表示,编写算法删除其值最大的结点.*/ /* 算法思想:使用pre,p,premax,max四个指针,pre和p进行比较,premax和max进行最后的删除操作 通过遍 ...

  4. 链表习题(1)-设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点

    /*设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点*/ /* 算法思想:设f(L,x)的功能是删除以L为首结点指针的单链表中所有值等于x的结点, 则显然有f(L->next,x)的 ...

  5. 有一个线性表,采用带头结点的单链表L来存储,设计一个算法将其逆置,且不能建立新节点,只能通过表中已有的节点的重新组合来完成。

    有一个线性表,采用带头结点的单链表L来存储,设计一个算法将其逆置,且不能建立新节点,只能通过表中已有的节点的重新组合来完成. 分析:线性表中关于逆序的问题,就是用建立链表的头插法.而本题要求不能建立新 ...

  6. 不带头结点的单链表------C语言实现

    File name:no_head_link.c Author:SimonKly Version:0.1 Date: 2017.5.20 Description:不带头节点的单链表 Funcion L ...

  7. 不带头结点的单链表(基于c语言)

    本篇文章的代码大多使用无头结点的单链表: 相关定义: #include <stdio.h> #include <stdlib.h> #include <assert.h& ...

  8. Python实现不带头结点的单链表

    1 # 创建一个节点类 2 class Node: 3 def __init__(self, item): 4 self.item = item 5 self.next = None 6 7 8 # ...

  9. 不带头结点的单链表递归删除元素为X的结点

    #include <iostream> using namespace std; struct Node { Node *next; int elem; }; void creatList ...

随机推荐

  1. mybatis入门教程之搭建一个简单的mybatis项目并启动它

    一.准备条件: 1.依赖jar包:mybatis核心包(必须).lombok插件包(非必须)以及MySQL数据库连接驱动包(必须) <dependency> <groupId> ...

  2. mysql过滤复制

  3. 【System】I/O密集型和CPU密集型工作负载之间有什么区别

    CPU密集型(CPU-bound) CPU密集型也叫计算密集型,指的是系统的硬盘.内存性能相对CPU要好很多,此时,系统运作大部分的状况是CPU Loading 100%,CPU要读/写I/O(硬盘/ ...

  4. 物理STANDBY库创建还原点(打开为read write后再变回主库)

    开启STANDBY库为READ WRITE 1.取消主库传送归档 SQL> alter system set log_archive_dest_state_2=defer; 2.取消备库应用日志 ...

  5. Git 沙盒模拟实战(远程篇)

    Git 沙盒模拟实战(远程篇) >---基础篇 远程仓库 远程仓库并不复杂, 在如今的云计算盛行的世界很容易把远程仓库想象成一个富有魔力的东西, 但实际上它们只是你的仓库在另个一台计算机上的拷贝 ...

  6. [分享] 最流行的 10 个 JavaScript 库

    1. Lodash https://github.com/lodash/lodash 一个工具库,用得还蛮多. 2. Chalk https://github.com/chalk/chalk 给终端加 ...

  7. LSTM+CRF进行序列标注

    为什么使用LSTM+CRF进行序列标注 直接使用LSTM进行序列标注时只考虑了输入序列的信息,即单词信息,没有考虑输出信息,即标签信息,这样无法对标签信息进行建模,所以在LSTM的基础上引入一个标签转 ...

  8. USB充电限流芯片,输出短路关闭,过压关闭

    PW1503,PW1502是超低RDS(ON)开关,具有可编程的电流限制,以保护电源源于过电流和短路保护.它具有超温保护以及反向闭锁功能. PW1503,PW1502采用薄型(1毫米)5针薄型SOT2 ...

  9. Navicat linux 官方最新版安装破解

    我们直接去官网下载linux版navicat 下载好之后执行命令打开软件 chmod +x navicat15-premium-cs.AppImage ./navicat15-premium-cs.A ...

  10. SQL Server 日志收缩方法

    在日常运维中,有时会遇到"The transaction log for database 'xxxx' is full due to 'ACTIVE_TRANSACTION'." ...