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 ...
随机推荐
- 细说 js 的7种继承方式
在这之前,先搞清楚下面这个问题: function Father(){} Father.prototype.name = 'father'; Father.prototype.children = [ ...
- SpringSecurity应用篇
前面吹水原理吹了一篇幅了,现在讲解下应用篇幅,前面说过,如果要用SpringSecurity的话要先导入一个包 <dependency> <groupId>org.spring ...
- git revert 回退已经push的内容
如题,在日常的开发过程中,可能有组员不小心一下子吧文件修改,需要进行回退 回退主要涉及到2种命令,一种是git reset 一种是 git revert git reset 会修改git log提交历 ...
- Spark Streaming处理Flume数据练习
把Flume Source(netcat类型),从终端上不断给Flume Source发送消息,Flume把消息汇集到Sink(avro类型),由Sink把消息推送给Spark Streaming并处 ...
- SDUST数据结构 - chap6 树与二叉树
判断题: 选择题: 函数题: 6-1 求二叉树高度: 裁判测试程序样例: #include <stdio.h> #include <stdlib.h> typedef char ...
- 你这样用过DO循环吗?
DATA: BEGIN OF text, word1(4) TYPE c VALUE 'This', word2(4) TYPE c VALUE 'is', ...
- Android事件分发机制二:viewGroup与view对事件的处理
前言 很高兴遇见你~ 在上一篇文章 Android事件分发机制一:事件是如何到达activity的? 中,我们讨论了触摸信息从屏幕产生到发送给具体 的view处理的整体流程,这里先来简单回顾一下: 触 ...
- bootstrap 后端模板
Twitter Bootstrap 框架已经广为人知,用于加快网站,应用程序或主题的界面开发,并被公认为是迄今对于 Web 开发的最有实质性帮助的工具之一.在此之前的,各种各样的界面库伴随着高昂的维护 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(89)-国际化,本地化,多语言应用
开篇 早年写过一篇多语言的应用 : 本地化(多语言) 讲述了如何创建多语言的资源文件,并利用资源文件来获得页面和请求的语言属性 本次补充这篇文章,的原因是在实际项目中,有多种需要多语言的情况 ...
- 前端知识(二)01-NPM包管理器-谷粒学院
目录 一.简介 二.使用npm管理项目 1.项目初始化 2.修改npm镜像 3.npm install命令的使用 4.其它命令 一.简介 什么是NPM NPM全称Node Package Manage ...