无头结点的单链表(C语言)

1.单链表:

  在顺序表中,用一组地址连续的存储单元来一次存放线性表的结点,因此结点的逻辑顺序与物理顺序是一致的。但链表却不同,链表是用一组任意的存储单元来存放 线性表的结点,这组存储单元可以是连续的,也可以是非连续的,甚至是零散分布在内存的任何位置上。因此,链表中结点的逻辑顺序与物理顺序不一定相同。为了正确表示节点间的逻辑关系,必须在存储线性表的每个数据元素的同时,存储指示其后继结点的地址信息,这两部分信息共同构成了单链表结点的结构,如下图:

结点包括两个域,数据域用来存放结点的值,指针域用来存储数据元素的直接后继的地址(或位置)。线性表正是通过每个结点的指针域将线性表的n个结点按其逻辑顺序连接在一起的。由于此线性表的每个节点只有一个next指针域,故将这种链表叫做单链表。

由于单链表中的每一个结点除了第一个节点外,它们的存储地址存放在其前驱结点的指针域中,由于第一个节点无前驱,所以应该设一个头指针指向第一个节点,本文中设置了first指针指向第一个结点。单链表中的最后一个节点无直接后继,所以指定单链表的最后一个结点的指针域为"空"(NULL)。

  一般情况下,使用链表,只关心链表中结点的逻辑顺序,并不关心每个结点的实际存储位置,因此通常用箭头来表示链域中的指针,于是链表就可以更直观地画成用箭头链接起来的结点序列,如图:

  有时候,为了操作的统一方便,可以在单链表的第一个结点前附设一个头结点,头结点的数据域可以存储一些关于线性表的长度等附加信息,也可以不存储任何信息,对头结点的数据域无特别规定,而头结点的指针域用来存储指向第一个结点的指针(即第一个结点的存储位置)。如果线性表为空,则头结点的指针域为"空"。如图所示:

      

2.单链表操作

   头插过程:

  头插的方式如上图所示。采用头插法得到的单链表的逻辑顺序与输入元素顺序相反,亦称头插法为逆序建表法。在这只介绍头插法的示意图,对于尾插、头删、尾删、可以参考《数据结构----用C语言描述》(耿国华主编)这本书。下面的代码中,实现了头插、尾插、头删、尾删,读者可以仔细研究研究。(本文所编写的代码是在VS2013编译环境下运行的)

3.运行代码:

  Linklist.h文件包括各个操作函数的声明以及包含的头文件,test.c包含了测试代码,Linklist.c文件里主要是各个操作函数的具体实现。

 1 //Linklist.h
 2 #pragma once
 3 #include<stdio.h>
 4 #include<assert.h>
 5 #include<stdlib.h>
 6
 7 typedef int LDataType;
 8 typedef struct Linklist
 9 {
10     LDataType data;
11     struct Linklist *next;
12 }Linklist, *pLinklist;
13
14 //接口函数
15 pLinklist BuyNewNode(LDataType data);//动态生成新节点
16 void InitLinklist(pLinklist *pL);//初始化单链表
17 void PushBackLinklist(pLinklist *pL, LDataType data);//尾插
18 void PushFrontLinklist(pLinklist *pL, LDataType data);//头插
19 void PopBackLinklist(pLinklist *pL);//尾删
20 void PopFrontLinklist(pLinklist *pL);//头删
21 void PrintLinklist(Linklist *pL);//打印单链表
22 pLinklist FindLinklist(pLinklist *pL, LDataType data);//查找指定元素,返回指定元素的位置
23 void InsertLinklist(pLinklist *pL, pLinklist p, LDataType data);//指定位置插入
24 void RemoveLinklist(pLinklist *pL, LDataType data);//删除第一个指定元素
25 void RemoveAllLinklist(pLinklist *pL, LDataType data);//删除所有的指定元素
26 int IsEmptyLinklist(pLinklist pL);//判断链表是否为空,为空返回1;不为空返回0;
27 void DestoryLinklist(pLinklist *pL);//销毁单链表
  1 //Linklist.c
  2 #include"Linklist.h"
  3 pLinklist BuyNewNode(LDataType data)//生成新节点
  4 {
  5     pLinklist NewNode = (pLinklist)malloc(sizeof(Linklist));
  6     if (NewNode == NULL)
  7     {
  8         printf("动态开辟内存空间失败\n");
  9         return;
 10     }
 11     NewNode->data = data;
 12     NewNode->next = NULL;
 13     return NewNode;
 14 }
 15 void InitLinklist(pLinklist *pL)//初始化
 16 {
 17     assert(pL != NULL);
 18     (*pL) = NULL;
 19 }
 20 void PushBackLinklist(pLinklist *pL, LDataType data)//尾插
 21 {
 22     assert(pL != NULL);
 23     pLinklist NewNode = BuyNewNode(data);
 24     if (*pL == NULL)
 25     {
 26         *pL = NewNode;
 27         return;
 28     }
 29     pLinklist cur = *pL;
 30     while (cur->next)
 31     {
 32         cur = cur->next;
 33     }
 34     cur->next = NewNode;
 35 }
 36 void PushFrontLinklist(pLinklist *pL, LDataType data)//头插
 37 {
 38     assert(pL != NULL);
 39     pLinklist NewNode = BuyNewNode(data);
 40     if (*pL == NULL)
 41     {
 42         *pL = NewNode;
 43         return;
 44     }
 45     NewNode->next = *pL;
 46     *pL = NewNode;
 47 }
 48 int IsEmptyLinklist(pLinklist pL)//判断是否为空链表
 49 {
 50     if (pL == NULL)
 51         return 1;
 52     return 0;
 53 }
 54 void PopBackLinklist(pLinklist *pL)//尾删
 55 {
 56     assert(pL != NULL);
 57     if (IsEmptyLinklist(*pL))//链表为空,没有节点
 58     {
 59         printf("链表为空,删除操作失败\n");
 60         return;
 61     }
 62     pLinklist cur = *pL;
 63     pLinklist pre = NULL;//保存cur的前一个节点
 64     if (cur->next == NULL)//有一个节点
 65     {
 66         *pL = NULL;
 67         free(cur);
 68         cur = NULL;
 69         return;
 70     }
 71     while (cur->next)
 72     {
 73         pre = cur;
 74         cur = cur->next;
 75     }
 76     pre->next = NULL;
 77     free(cur);
 78     cur = NULL;
 79 }
 80 void PopFrontLinklist(pLinklist *pL)//头删
 81 {
 82     assert(pL != NULL);
 83     if (*pL == NULL)
 84     {
 85         printf("链表为空,删除操作失败\n");
 86         return;
 87     }
 88     pLinklist cur = *pL;
 89     *pL = cur->next;
 90     free(cur);
 91     cur = NULL;
 92 }
 93 pLinklist FindLinklist(pLinklist *pL, LDataType data)//查找指定元素,返回指定元素的位置
 94 {
 95     assert(pL != NULL);
 96     pLinklist cur = *pL;
 97     while (cur)
 98     {
 99         if (cur->data == data)
100         {
101             return cur;
102         }
103         cur = cur->next;
104     }
105     return NULL;
106 }
107 void InsertLinklist(pLinklist *pL, pLinklist p, LDataType data)//指定位置前面插入
108 {
109     assert(pL != NULL);
110     pLinklist NewNode = BuyNewNode(data);
111     pLinklist cur = *pL;
112     while (cur->next != p)
113     {
114         cur = cur->next;
115     }
116     NewNode->next = p;
117     cur->next = NewNode;
118 }
119 void RemoveLinklist(pLinklist *pL, LDataType data)//删除第一个指定元素
120 {
121     assert(pL != NULL);
122     pLinklist cur = NULL;
123     pLinklist p = *pL;
124     pLinklist pre = NULL;
125     cur = FindLinklist(pL, data);//找到要删除的指定元素
126     if (cur == NULL)
127     {
128         printf("没找到要删除的指定元素,删除失败\n");
129         return;
130     }
131     if (*pL == cur)//位于第一个节点
132     {
133         *pL= cur->next;
134         free(cur);
135         cur = NULL;
136         return;
137     }
138     while (p!= cur)
139     {
140         pre = p;
141         p = p->next;
142     }
143     pre->next = cur->next;
144     free(cur);
145     cur = NULL;
146 }
147 void RemoveAllLinklist(pLinklist *pL, LDataType data)//删除所有的指定元素
148 {
149     assert(pL != NULL);
150     pLinklist cur = NULL;
151     pLinklist p = *pL;
152     pLinklist pre = *pL;
153     while (p)
154     {
155
156         if (p->data == data && (*pL) == p)
157         {
158             pre = p;
159             p = p->next;
160             *pL = p;
161             free(pre);
162             pre = NULL;
163         }
164         else if (p->data == data)
165         {
166             cur = p;
167             p = p->next;
168             pre->next = p;
169             free(cur);
170             cur = NULL;
171         }
172         else
173         {
174             pre = p;
175             p = p->next;
176         }
177     }
178
179 }
180 void PrintLinklist(Linklist *pL)//打印单链表
181 {
182     pLinklist cur = pL;
183     while (cur)
184     {
185         printf("%d-->", cur->data);
186         cur = cur->next;
187     }
188     printf("NULL\n");
189 }
190 void DestoryLinklist(pLinklist *pL)//销毁单链表,放置内存溢出
191 {
192     assert(pL != NULL);
193     pLinklist cur = *pL;
194     pLinklist pre = NULL;//保存cur的前一个节点
195     if (*pL == NULL)
196     {
197         printf("链表为空\n");
198         return;
199     }
200     if (cur->next == NULL)//只有一个节点
201     {
202         *pL = NULL;
203         free(cur);
204         cur = NULL;
205         return;
206     }
207     while (cur)
208     {
209         pre = cur;
210         cur = cur->next;
211         free(pre);
212         pre = NULL;
213     }
214 }
 1 //test.c测试函数
 2 #include"Linklist.h"
 3
 4 void test()
 5 {
 6     pLinklist cur = NULL;//用来接收FindLinklist的返回值
 7     Linklist *first = NULL;
 8     InitLinklist(&first);//初始化
 9     //PushBackLinklist(&first, 1);//尾插元素
10     //PushBackLinklist(&first, 2);
11     //PushBackLinklist(&first, 3);
12     //PushBackLinklist(&first, 4);
13     //PushBackLinklist(&first, 5);
14     //PrintLinklist(first);//打印单链表
15     PushFrontLinklist(&first, 6);//头插元素
16     PushFrontLinklist(&first, 7);
17     PushFrontLinklist(&first, 8);
18     PushFrontLinklist(&first, 9);
19     PushFrontLinklist(&first, 10);
20     //PopBackLinklist(&first);//尾删一个节点
21     //PopFrontLinklist(&first);//头删一个节点
22     //PrintLinklist(first);//打印单链表
23     //DestoryLinklist(&first);
24     //cur = FindLinklist(&first, 8);
25     //InsertLinklist(&first, cur, 11);
26     //printf("在8前面插入11得:");
27     //PrintLinklist(first);//打印单链表
28     //printf("删除11得:");
29     //RemoveLinklist(&first, 11);
30     //PrintLinklist(first);
31     PushFrontLinklist(&first, 7);
32     PushFrontLinklist(&first, 7);
33     //RemoveLinklist(&first, 7);
34     RemoveAllLinklist(&first, 7);
35     PrintLinklist(first);
36
37     //RemoveAllLinklist(&first, 7);//删除所有的7
38 }
39 int main()
40 {
41     test();
42     system("pause");
43     return 0;
44 }

 4.尾插法建立单链表如下图:

  测试图:                                                                                                                         运行图:

 

 5.头插法建立单链表如下图:

   测试图:                                                                                    运行图:

 

6.头删和尾删一个结点:

  测试图:                                                                              运行图:

 

 7.在指定位置插入元素:

  测试图:                                                                          运行图:

 

   除这几个操作外,还有删除指定元素RemoveLinklist(删除第一个找到的指定元素),删除所有的指定元素RemoveAllLinklist。因为本文中单链表的结点是动态开辟的,因此还要实现销毁函数DestoryLinklist,防止内存泄漏。

原文地址:https://www.cnblogs.com/love-you1314/p/9690855.html

时间: 2024-10-10 13:36:56

无头结点的单链表(C语言)的相关文章

关于有头结点和无头结点的单链表

p88X17曰潦侔1骋VLhttp://www.docin.com/app/user/userinfo?userid=179117005 锨断579吵4庞QGhttp://www.docin.com/app/user/userinfo?userid=179254593 Sf2AI霞纪猿1僬AQ5http://tushu.docin.com/undz630 3Fg毒卤诼7M糖关丫7PFhttp://docstore.docin.com/zzs15907 h9日攘耐汉j粟淄3蹦Zhttp://shu

对带头结点的单链表的简单操作

#pragma once #include<stdio.h> #include<stdlib.h> #include<assert.h> #include<memory.h> #define DataType int           //int 可以改写为其它数据类型 typedef struct Node { DataType data; struct Node *next; }Node,*pNode;          //定义结点结构体      

线性表带头结点的单链表的链式表示和实现

带有头结点的单链表的12个基本操作 #define DestroyList ClearList//DestroyList()和ClearList()的操作是一样的 void InitList(LinkList &L){ L = NULL; } void ClearList(LinkList &L){ LinkList p; while (L){ p = L; L = L->next; free(p); } } Status ListEmpty(LinkList L){ if (L)r

带头结点的单链表操作说明

一.单链表简介 相对于以数组为代表的"顺序表"而言,单链表虽然存储密度比较低(因为数据域才是我们真正需要的,指针域只是用来索引,我们并不真正需要它),但是却具有灵活分配存储空间.方便数据元素的删除.方便元素插入等优点 单链表是线性表链式存储的一种,其储存不连续.单链表的数据结构中包含两个变量:数据和指向下一结点的指针.一个结点只知道下一个结点的地址.一个单链表必须有一个头指针,指向单链表中的第一个结点.否则链表会在内存中丢失. 一般的链表可以不带头结点,头指针直接指向第一个节点,如下图

03.带头结点的单链表

/** * 带头结点的单链表 */ public class LinkListDemo { public static void main(String[] args){ Node n1 = new Node(1,"A"); Node n2 = new Node(2,"B"); Node n3 = new Node(3,"C"); Node n4 = new Node(4,"D"); // LinkList linkList

链表习题(4)-有一个带头结点的单链表,编写算法使其元素递增有序

1 /*有一个带头结点的单链表,编写算法使其元素递增有序*/ 2 /* 3 算法思想:利用直接插入排序的思想,先构成只含有一个数据结点的有序单链表,然后依次插入 4 剩余结点到合适的位置. 5 */ 6 void Sort(LinkList& L) 7 { 8 LNode *p = L->next, *pre; 9 LNode *r = p->next; 10 p->next = NULL; 11 while (p) 12 { 13 r = p->next; 14 pre

(含有头结点以及尾结点)单链表各类功能的实现

对单链表实现如下功能: void InitList(List *list); //初始化单链表 bool push_back(List *list,ElemType x); //尾插法 void show_seqlist(List *list); //显示链表内容 bool push_front(List *list,ElemType x);//头插法 bool pop_back(List *list); //尾删法 bool pop_front(List *list); //头删法 Node

带头节点的单链表-------C语言实现

1 /***************************************************** 2 Author:Simon_Kly Version:0.1 Date:20170520 3 Description:带头接点的单链表 4 Mail:[email protected] 5 Funcion List: 6 *****************************************************/ 7 8 #include <stdio.h> 9 #

线性表的链式存储结构(带头结点的单链表)

首先,我们定义带头节点的单链表存储结构如下: 1 /* 2 ** 线性表的单链表存储结构定义 */ 3 typedef int ListElemType;//线性表数据元素类型 4 typedef struct tagLNode { 5 ListElemType data; 6 struct tagLNode *next; 7 }LNode, *LinkList; 在此基础上可以执行的基本操作如下: 1 #include "linklist_algo.h" 2 #include <