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. (二)数据源处理5-excel数据转换实战(上)

    把excel_oper02.py 里面实现的:通过字典的方式获取所有excel数据.放进utils: ️️️️️️️️️️️️️️️️️️️️️️️️️️️️️️️ utils: def get_al ...

  2. maven仓库和镜像

    目录 简介 本地仓库 远程仓库 远程仓库的更新 远程仓库的认证 部署到远程仓库 快照版本 依赖解析 镜像 本文主要是针对<maven实战>书中关键知识点的学习记录,未免有纰漏或描述不到之处 ...

  3. .NET 5网络操作的改进

    随着.net 5在11月的发布,现在是谈论网络栈中许多改进的好时机.这包括对HTTP.套接字.与网络相关的安全性和其他网络通信的改进.在这篇文章中,我将重点介绍一些版本中更有影响力和更有趣的变化. H ...

  4. docker 常用的容器命令

    容器命令 # --name 给容器起名 # -p 端口映射 # -d 后台启动 # -it 交互模式启动 # 交互模式启动 # docker run -it 镜像名/id /bin/bash # do ...

  5. C#中foreach的实现原理

    C#中foreach的实现原理 在探讨foreach如何内部如何实现这个问题之前,我们需要理解两个C#里边的接口,IEnumerable 与 IEnumerator. 在C#里边的遍历集合时用到的相关 ...

  6. python sqlite3增加表字段

    给sqlite3表格增加新字段,要注意大小写,要不然不成功. 一开始这样写,不成功! 后面规范写,按大小写严格规范写! 成功了!现在查看新增加的字段commit: 仔细看,这下全部小写,括表名称.co ...

  7. WCNSS_qcom_cfg.ini WIFI配置文件参数详细解析

    STA相关的一般配置 参数 含义 最小值 最大值 默认值 gNeighborLookupThreshold 1 触发roam scan发生的条件在WCNSS_qcom_cfg.ini文件中gNeigh ...

  8. 【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据

    任务描述 本次集中介绍使用Windows和Linux()搭建本地Redis服务器的步骤,从备份的RDB文件中加载数据,以及如何生成AOF文件和通过AOF文件想已经运行的Redis追加数据. 操作步骤 ...

  9. JavaScript中eval的替代方法

    引自:https://www.cnblogs.com/lxg0/p/7805266.html 通常我们在使用ajax获取到后台返回的json数据时,需要使用 eval 这个方法将json字符串转换成对 ...

  10. selenium八大元素定位方法

    1.ID定位 可以根据元素的id来定位属性,id是当前整个HTML页面中唯一的,所以可以通过id属性来唯一定位一个元素,是首选的元素定位方式.(动态ID不做考虑) # 导入webdriver和By f ...