c语言实现--不带头结点的单链表操作
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语言实现--不带头结点的单链表操作的更多相关文章
- java编写带头结点的单链表
最近在牛客网上练习在线编程,希望自己坚持下去,每天都坚持下去练习,给自己一个沉淀,不多说了 我遇到了一个用java实现单链表的题目,就自己在做题中将单链表完善了一下,希望大家作为参考也熟悉一下,自己 ...
- C/C++中创建(带头结点、不带头结点的)单链表
1.带头结点的单链表(推荐使用带头结点的单链表)(采用尾插法) 了解单链表中节点的构成 从上图可知,节点包含数据域和指针域,因此,在对节点进行定义时,我们可以如下简单形式地定义: /* 定义链表 */ ...
- 链表习题(2)-一个集合用带头结点的单链表L表示,编写算法删除其值最大的结点。
/*一个集合用带头结点的单链表L表示,编写算法删除其值最大的结点.*/ /* 算法思想:使用pre,p,premax,max四个指针,pre和p进行比较,premax和max进行最后的删除操作 通过遍 ...
- 链表习题(1)-设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点
/*设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点*/ /* 算法思想:设f(L,x)的功能是删除以L为首结点指针的单链表中所有值等于x的结点, 则显然有f(L->next,x)的 ...
- 有一个线性表,采用带头结点的单链表L来存储,设计一个算法将其逆置,且不能建立新节点,只能通过表中已有的节点的重新组合来完成。
有一个线性表,采用带头结点的单链表L来存储,设计一个算法将其逆置,且不能建立新节点,只能通过表中已有的节点的重新组合来完成. 分析:线性表中关于逆序的问题,就是用建立链表的头插法.而本题要求不能建立新 ...
- 不带头结点的单链表------C语言实现
File name:no_head_link.c Author:SimonKly Version:0.1 Date: 2017.5.20 Description:不带头节点的单链表 Funcion L ...
- 不带头结点的单链表(基于c语言)
本篇文章的代码大多使用无头结点的单链表: 相关定义: #include <stdio.h> #include <stdlib.h> #include <assert.h& ...
- Python实现不带头结点的单链表
1 # 创建一个节点类 2 class Node: 3 def __init__(self, item): 4 self.item = item 5 self.next = None 6 7 8 # ...
- 不带头结点的单链表递归删除元素为X的结点
#include <iostream> using namespace std; struct Node { Node *next; int elem; }; void creatList ...
随机推荐
- Macbook 安装Windows的完美教程
[原文](http://www.melodydance.top/mac-win.html) 1. 背景 Windows相对于Mac市场占有率更高,对很多人来说Windows使用起来更方便,以至于很多人 ...
- MongoDB Sharding(一) -- 分片的概念
(一)分片的由来随着系统的业务量越来越大,业务系统往往会出现这样一些特点: 高吞吐量 高并发 超大规模的数据量 高并发的业务可能会耗尽服务器的CPU,高吞吐量.超大规模的数据量也会带来内存.磁盘的压力 ...
- HashMap为什么效率高?来看看这个小demo
一.前情回顾:在程序中有时候需要存放对象,容器应运而生.容器分为集合和Map.集合在这里不说,说说Map.Map在英语中是地图的意思,这个名字真是起的好,可以让人顾名思义.Map,就是存放键值对的结构 ...
- 利用Numpy求解投资内部收益率IRR
一. 内部收益率和净现值 内部收益率(Internal Rate of Return, IRR)其实要和净现值(Net Present Value, NPV)结合起来讲.净现值指的是某个投资项目给公司 ...
- WPF NET5 Prism8.0的升级指南
前言 曾经我以学习的目的写了关于在.NET Core3.1使用Prism的系列文章.NET Core 3 WPF MVVM框架 Prism系列文章索引,也谢谢大家的支持,事实上当初的版本则是Pri ...
- oracle rac切换到单实例DG后OGG的处理
在RAC切换到单实例DG后,将OGG目录复制过去,在使用alter extract ext_name,begin now的时候报错 2016-04-10 11:27:03 WARNING OGG-01 ...
- SQL Server management studio使用sa连接时报错与伺服器的连接已成功,但在登入程序是发生错误
使用Sql Server management studio的sa用户连接数据库时,报如下错误 解决方法: 1.使用windows验证登录 2.右键点击连接,点击属性,点击安全性,选择混合验证 3.重 ...
- 基于Asp.Net Core 5.0依赖Quartz.Net框架编写的任务调度web管理平台
源码地址: https://github.com/246850/Calamus.TaskScheduler 演示地址:http://47.101.47.193:1063/ 1.Quartz.NET框架 ...
- Git 沙盒模拟实战(远程篇)
Git 沙盒模拟实战(远程篇) >---基础篇 远程仓库 远程仓库并不复杂, 在如今的云计算盛行的世界很容易把远程仓库想象成一个富有魔力的东西, 但实际上它们只是你的仓库在另个一台计算机上的拷贝 ...
- 视频画面中实现人脸遮挡教程 - 基于 TensorFlow 实现
在进行视频通话时,我们往往需要对画面进行一些实时分析,例如识别画面里的人.车.动物等等.这节里我们将使用时信魔方的人脸监视模块实现人脸被手部遮挡的检测,如下图所示效果: 预备知识 时信魔方的客户端使用 ...