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. 【Linux】fio测试读写速度

    需要安装fio yum install fio -y 有很多依赖包     FIO用法: 随机读:(可直接用,向磁盘写一个2G文件,10线程,随机读1分钟,给出结果) fio -filename=/h ...

  2. 【ORA】ORA-01078和LRM-00109 解决方法

    今天切换到asm实例的时候,发现是一个空实例,尝试启动实例,结果报错ORA-01078和LRM-00109 SQL> startupORA-01078: failure in processin ...

  3. Sentry(v20.12.1) K8S 云原生架构探索,JavaScript 性能监控之管理 Transactions

    系列 Sentry-Go SDK 中文实践指南 一起来刷 Sentry For Go 官方文档之 Enriching Events Snuba:Sentry 新的搜索基础设施(基于 ClickHous ...

  4. Description Resource Path Location Type Failure to transfer org.apache.maven.plugins:maven-surefire-

    url:https://www.pianshen.com/article/8003307916/ Description Resource Path Location Type Failure to ...

  5. python 字典(formkey 建立 取值 赋值 删除 )

      formkey快速建立空字典   result = {}.fromkeys(['name','age','job'],None) print(result)   #往字典里添加元素 result. ...

  6. 网络基础知识之Cisco

    2021-01-2313:35:21 大家好,我是新手,刚学完Cisco协议,以后,我会每天都会给大家一些学习笔记 和一些学习心得,这方面不会的可以找我.qq2934896930. 网络的定义: 计算 ...

  7. 前序遍历 排序 二叉搜索树 递归函数的数学定义 return 递归函数不能定义为内联函数 f(x0)由f(f(x0))决定

    遍历二叉树   traversing binary tree 线索二叉树 threaded binary tree 线索链表 线索化 1. 二叉树3个基本单元组成:根节点.左子树.右子树 以L.D.R ...

  8. Redis 雪崩、穿透和击穿

    https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/redis-caching-avalanche-and ...

  9. WPF mvvm 验证,耗时两天的解决方案

    常用类 类名 介绍 ValidationRule 所有自定义验证规则的基类.提供了让用户定义验证规则的入口. ExceptionValidation 表示一个规则,该规则检查在绑定源属性更新过程中引发 ...

  10. 这几个小技巧,让你书写不一样的Vue!

    前言 最近一直在阅读Vue的源码,发现了几个实战中用得上的小技巧,下面跟大家分享一下. 同时也可以阅读我之前写的Vue文章 vue开发中的"骚操作" 挖掘隐藏在源码中的Vue技巧! ...