设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 手机 数据 公司
当前位置: 首页 > 服务器 > 安全 > 正文

【数据结构】单链表amp;amp;静态链表详解和代码实例

发布时间:2021-03-31 13:25 所属栏目:53 来源:网络整理
导读:喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号【程序猿声】 01 单链表(Singly Linked List ) 1.1 什么是单链表? 单链表是一种链式存储的结构。它动态的为节点分配存储单元。当有节点插入时,系统动态的为结点分配空间。在结点删除时,应该及

喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号【程序猿声】

01 单链表(Singly Linked List )

1.1 什么是单链表?

单链表是一种链式存储的结构。它动态的为节点分配存储单元。当有节点插入时,系统动态的为结点分配空间。在结点删除时,应该及时释放相应的存储单元,以防止内存泄露。由于是链式存储,所以操作单链表时,必须知道头结点或者头指针的位置。并且,在查找第i个节点时,必须找到第i-1个节点。

1.2 单链表的存储结构代码描述

对于链式存储,通过上一节的讲解相信大家已经了解得够清楚了。如下图所示:

【数据结构】单链表amp;amp;静态链表详解和代码实例

下面我们来看看单链表存储是如何用代码来实现的。

1//单链表的存储结构C语言代码
2typedef?struct?SListNode
3{
4????datatype?data;????//数据域
5????struct?SListNode?*?pnext;//指针域
6}SLinkList;

由上面的结构我们可以看出,一个节点由存放数据的数据域和存放地址的指针域组成。假如p指向了第i个节点,那么p->data就是该节点存放的数据,而p->pnext自然就是指向下一个节点的指针。如下图所示:

【数据结构】单链表amp;amp;静态链表详解和代码实例

那么接下来我们看看单链表的各个操作具体实现吧。(只讲几个关键步骤)
备注:下面的代码基于这样的一个单链表:

  • 有一个头指针phead
  • 有一个头结点node
  • 头指针指向头结点,头结点位置记为0

1.3 单链表的读取

在拿到头指针以后,单链表的读取也并非一件难事。一开始设置一个计数变量,不断遍历链表,让计数器自增。找到合适的位置将数据读取出来。具体代码实现如下:

 1#define?status?bool
2#define?ERROR?false
3#define?OK?true
4/*
5?*?函数功能:获取位置index节点的数据
6?*?参数说明:phead链表头结点,e用来获取的变量,index索引
7*/
8
9status?GetSListIndexNode(Node?*?phead,DType?*e,?int?index)
10{
11????int?icount?=?0;?//计数器
12????//注:0号位为头结点,头结点不存放任何数据
13????if?(phead->pnext?==?nullptr?||?index?<?1?||?index?>?GetSListLength()/*此处为链表长度*/)
14????{
15????????return?ERROR;?//异常?处理
16????}
17????while?(phead->pnext?!=?nullptr)
18????{
19????????icount++;
20????????phead?=?phead->pnext;
21????????if?(icount?==?index)
22????????{
23????????????*e?=?phead->data;
24????????????return?OK;
25????????}
26????}
27????return?ERROR;
28}

1.4 单链表的插入

1.4.1 指定位置后插

其实链表的插入和删除都是很简单的操作,初学者只要抓住指针指向的节点,并加以区分开来,就很easy了。如下图:

【数据结构】单链表amp;amp;静态链表详解和代码实例

图中,假如此时p指向了我们要插入的节点的位置。那么,怎样把我们的S节点给插入到p指向的节点之后?在这里我们先不要惊动p以及p后面的节点:

  1. 我们先让S节点指向p之后的节点(步骤①)
  2. 之后我们切断p和p后面那个节点的关系(步骤②)
  3. 最后让p节点的指针域指向s节点(步骤③),搞定

算法描述:

  1. 声明一个指针p指向链表头结点,向后遍历p=p->next,找到正确的位置。
  2. 新建一个结点s。
  3. s->next = p->next ①
  4. p->next = s ②③
    具体代码如下:
 1#define?status?bool
2#define?ERROR?false
3#define?OK?true
4/*
5?*?函数功能:指定位置后插
6?*?参数说明:phead链表头结点,IData插入的数据,index索引
7*/
8status?InsertSListNodeFront(Node?*?phead,?DType?IData,?int?index)
9{
10????if?(phead->pnext?==?nullptr?||?index?<?1?||?index?>?GetSListLength())
11????{
12????????return?ERROR;?//异常?处理
13????}
14????int?iCount?=?0;?//计数器
15????Node<DType>?*?q?=?nullptr;?//备用
16????while?(phead->pnext?!=?nullptr)
17????{
18????????iCount++;
19????????q?=?phead;
20????????phead?=?phead->pnext;
21????????if?(?iCount?==?index?)
22????????{
23????????????Node<DType>?*?p?=?new?Node<DType>;
24????????????p->data?=?IData;
25????????????p->pnext?=?phead;
26????????????q->pnext?=?p;???//前插
27????????????return?OK;
28????????}
29????}
30????return?ERROR;
31}
1.4.2 指定位置前插

咳咳,聪明的小伙伴,用脑子想想。指定位置前插 == 指定位置的前一个位置进行后插。懂了吧?直接看具体代码:

 1/*
2?*?函数功能:指定位置后插
3?*?参数说明:phead链表头结点,IData插入的数据,index索引
4*/
5status?InsertSListNodeBack(Node?*?phead,?int?index)
6{
7????if?(phead->pnext?==?nullptr?||?index?<?1?||?index?>?GetSListLength())
8????{
9????????return?ERROR;?//异常?处理
10????}
11????int?iCount?=?0;?//计数器
12????Node<DType>?*?q?=?nullptr;?//备用
13????while?(phead->pnext?!=?nullptr)
14????{
15????????iCount++;
16????????q?=?phead;
17????????phead?=?phead->pnext;
18????????if?(iCount?==?index)
19????????{
20????????????Node<DType>?*?p?=?new?Node<DType>;
21????????????q?=?phead;
22????????????phead?=?phead->pnext;?//后插就是后一个节点的前插咯
23????????????p->data?=?IData;
24????????????p->pnext?=?phead;
25????????????q->pnext?=?p;???
26????????????return?OK;
27????????}
28????}
29????return?ERROR;
30}

1.5 单链表的删除

单链表的删除其实也是很简单。只要比如要删除p指向的节点,只需要让p之前的节点的指针域直接指向p之后的节点,再把p给free就OK了。如下图:

【数据结构】单链表amp;amp;静态链表详解和代码实例

算法描述:

  1. 声明一个指针p指向链表头结点,向后遍历p=p->next,找到要删除的节点位置。
  2. q = p->next
  3. p->next = q->next ①②
  4. free(q) ③④

具体代码如下:

 1/*
2?*?函数功能:指定位置后插
3?*?参数说明:phead链表头结点,IData获取删除的数据,index索引
4*/
5//删除指定位置节点(e获取删除元素)
6template?<typename?DType>
7status?DeleteSListIndexNode(Node?*?phead,?DType?*e,?int?index)
8{
9????int?i?=?0;?//计数器
10????Node<DType>?*?q?=?nullptr;
11????if?(phead->pnext?==?nullptr?||?index?<?1?||?index?>?GetSListLength())
12????{
13????????return?ERROR;?//异常?处理
14????}
15????while?(phead->pnext?!=?nullptr)
16????{
17????????i++;
18????????q?=?phead;?//保存备用
19????????phead?=?phead->pnext;
20????????if?(i?==?index)
21????????{
22????????????*e?=?phead->data;
23????????????q->pnext?=?phead->pnext;?//删除出局
24????????????return?OK;
25????????}
26????}
27????return?ERROR;
28}

代码应该不难,相信大家都能很容易看懂。

1.6.1 单链表的完整代码

好了,前面介绍了几个重要的操作,接下来请大家看看完整的代码吧。小编为了使用方便,就用C++的class和template将整个链表封装到了一个类里面,通过模板实现泛型编程。

 1/*
2?*?文件名:SingleLinkList.h
3?*?说明?:类的各种声明
4?*/
5#pragma?once?//VC编译器防止头文件被重复包含的一条预编译指令
6
7#define?status?bool
8#define?OK?true
9#define?ERROR?false
10#define?YES?true
11#define?NO?false
12
13template?<typename?DType>
14class?Node
15{
16public:
17????DType?data;
18????Node?*?pnext;
19};
20
21template?<typename?DType>
22class?CSingleLinkList
23{
24private:
25????Node<DType>?*phead;?//链表头指针
26public:
27????CSingleLinkList();//构造,类被创建时调用
28????~CSingleLinkList();//析构,类被销毁时调用
29public:
30????//初始化链表
31????status?InitSList();
32????//获取链表长度
33????int?GetSListLength();
34????//增加一个节点?前插法
35????status?AddSListNodeFront(DType?idata);
36????//增加一个节点?后插法
37????status?AddSListNodeBack(?DType?idata);
38????//判断链表是否为空
39????status?IsSListEmpty();
40????//获取指定位置节点值(注意,本程序规定0号为头节点,e获取删除元素)
41????status?GetSListIndexNode(DType?*e,?int?index);
42????//删除指定位置节点(e获取删除元素)
43????status?DeleteSListIndexNode(DType?*e,?int?index);
44????//查找链表中指定值(pindex获取位置0==>not?found)
45????status?SearchSListNode(DType?SData,?int?*pindex);
46????//指定位置前插
47????status?InsertSListNodeFront(DType?IData,?int?index);
48????//指定位置后插
49????status?InsertSListNodeBack(DType?IData,?int?index);
50????//清空链表(保留根节点)
51????status?ClearSList();
52????//销毁链表(all?delete)
53????status?DestorySList();
54????//尾部删除一个元素
55????status?DeleteSListNodeBack();
56????//打印链表???此函数根据实际情况而定
57????void?PrintSList();
58};
59
60/*
61?*?文件名:SingleLinkList.cpp
62?*?说明?:类的各种方法的实现
63?*/
64
65#include?"SingleLinkList.h"
66#include?<stdio.h>
67
68template?<typename?DType>
69CSingleLinkList<DType>::CSingleLinkList()
70{
71????cout?<<?"链表创建"?<<?endl;
72????InitSList();
73}
74template?<typename?DType>
75CSingleLinkList<DType>::~CSingleLinkList()
76{
77????cout?<<?"链表销毁"?<<?endl;
78????DestorySList();
79}
80//初始化链表
81template?<typename?DType>
82status?CSingleLinkList<DType>::InitSList()
83{
84????Node<DType>?*?ph?=?new?Node<DType>;
85????if?(ph?!=?NULL)
86????{
87????????ph->pnext?=?nullptr;
88????????this->phead?=?ph;?//头结点
89????????return?OK;
90????}
91????return?ERROR;
92}
93//获取链表长度(head_node?is?not?included)
94template?<typename?DType>
95int?CSingleLinkList<DType>::GetSListLength()
96{
97????int?length?=?0;
98????Node<DType>?*?phead?=?this->phead;
99????while?(phead->pnext?!=?nullptr)
100????{
101????????length++;
102????????phead?=?phead->pnext;
103????}
104????return?length;
105}
106//增加一个节点?前插法
107template?<typename?DType>
108status?CSingleLinkList<DType>::AddSListNodeFront(?DType?idata)
109{
110????Node<DType>?*?pnode?=?new?Node<DType>;
111????if?(pnode?!=?NULL)
112????{
113????????pnode->data?=?idata;
114????????pnode->pnext?=?this->phead->pnext;
115????????this->phead->pnext?=?pnode;?//挂载
116
117????????//printf("pnode?=?%p??pnode->pnext?=?%p?this->phead->pnext?=?%p?this->phead?=?%p\n",?pnode,?pnode->pnext,?this->phead->pnext,?this->phead);
118????????return?OK;
119????}
120????return?ERROR;
121}
122
123
124//增加一个节点?尾插法
125template?<typename?DType>
126status?CSingleLinkList<DType>::AddSListNodeBack(DType?idata)
127{
128????Node<DType>?*?pnode?=?new?Node<DType>;
129????Node<DType>?*?phead?=?this->phead;
130????if?(pnode?!=?NULL)
131????{
132????????while?(phead->pnext?!=?nullptr)
133????????{
134????????????phead?=?phead->pnext;
135????????}
136????????pnode->data?=?idata;
137????????pnode->pnext?=?nullptr;
138????????phead->pnext?=?pnode;?//挂载
139????????return?OK;
140????}
141????return?ERROR;
142}
143//判断链表是否为空
144template?<typename?DType>
145status?CSingleLinkList<DType>::IsSListEmpty()
146{
147????if?(this->phead->pnext?==?nullptr)
148????{
149????????return?YES;
150????}
151????return?NO;
152}
153//获取指定位置节点值(注意,本程序规定0号为头节点,e获取节点的值)
154template?<typename?DType>
155status?CSingleLinkList<DType>::GetSListIndexNode(DType?*e,?int?index)
156{
157????Node<DType>?*?phead?=?this->phead;
158????int?i?=?0;?//计数器
159????if?(phead->pnext?==?nullptr?||?index?<?1?||?index?>?GetSListLength())
160????{
161????????return?ERROR;?//异常?处理
162????}
163????while?(phead->pnext?!=?nullptr)
164????{
165????????i++;
166????????phead?=?phead->pnext;
167????????if?(i?==?index)
168????????{
169????????????*e?=?phead->data;
170????????????return?OK;
171????????}
172????}
173????return?ERROR;
174}
175//删除指定位置节点(e获取删除元素)
176template?<typename?DType>
177status?CSingleLinkList<DType>::DeleteSListIndexNode(?DType?*e,?int?index)
178{
179????Node<DType>?*?phead?=?this->phead;
180????int?i?=?0;?//计数器
181????Node<DType>?*?q?=?nullptr;
182????if?(phead->pnext?==?nullptr?||?index?<?1?||?index?>?GetSListLength())
183????{
184????????return?ERROR;?//异常?处理
185????}
186????while?(phead->pnext?!=?nullptr)
187????{
188????????i++;
189????????q?=?phead;?//保存备用
190????????phead?=?phead->pnext;
191????????if?(i?==?index)
192????????{
193????????????*e?=?phead->data;
194????????????q->pnext?=?phead->pnext;?//删除出局
195????????????return?OK;
196????????}
197????}
198????return?ERROR;
199}
200//查找链表中指定值(pindex获取位置???0==>not?found)
201template?<typename?DType>
202status?CSingleLinkList<DType>::SearchSListNode(?DType?SData,?int?*pindex)
203{
204????Node<DType>?*?phead?=?this->phead;
205????int?iCount?=?0;//计数器
206????while?(phead->pnext?!=?nullptr)
207????{
208????????iCount++;
209????????phead?=?phead->pnext;
210????????if?(phead->data?==?SData)
211????????{
212????????????*pindex?=?iCount;
213????????????return?YES;
214????????}
215????}
216????*pindex?=?0;
217????return?NO;
218}
219//指定位置前插
220template?<typename?DType>
221status?CSingleLinkList<DType>::InsertSListNodeFront(DType?IData,?int?index)
222{
223????Node<DType>?*?phead?=?this->phead;
224????if?(phead->pnext?==?nullptr?||?index?<?1?||?index?>?GetSListLength())
225????{
226????????return?ERROR;?//异常?处理
227????}
228????int?iCount?=?0;?//计数器
229????Node<DType>?*?q?=?nullptr;?//备用
230????while?(phead->pnext?!=?nullptr)
231????{
232????????iCount++;
233????????q?=?phead;
234????????phead?=?phead->pnext;
235????????if?(?iCount?==?index?)
236????????{
237????????????Node<DType>?*?p?=?new?Node<DType>;
238????????????p->data?=?IData;
239????????????p->pnext?=?phead;
240????????????q->pnext?=?p;???//前插
241????????????return?OK;
242????????}
243????}
244????return?ERROR;
245}
246//指定位置后插
247template?<typename?DType>
248status?CSingleLinkList<DType>::InsertSListNodeBack(?DType?IData,?int?index)
249{
250????Node<DType>?*?phead?=?this->phead;
251????if?(phead->pnext?==?nullptr?||?index?<?1?||?index?>?GetSListLength())
252????{
253????????return?ERROR;?//异常?处理
254????}
255????int?iCount?=?0;?//计数器
256????Node<DType>?*?q?=?nullptr;?//备用
257????while?(phead->pnext?!=?nullptr)
258????{
259????????iCount++;
260????????q?=?phead;
261????????phead?=?phead->pnext;
262????????if?(iCount?==?index)
263????????{
264????????????Node<DType>?*?p?=?new?Node<DType>;
265????????????q?=?phead;
266????????????phead?=?phead->pnext;?//后插就是后一个节点的前插咯
267????????????p->data?=?IData;
268????????????p->pnext?=?phead;
269????????????q->pnext?=?p;???
270????????????return?OK;
271????????}
272????}
273????return?ERROR;
274}
275//清空链表(保留根节点)
276template?<typename?DType>
277status?CSingleLinkList<DType>::ClearSList()
278{
279????Node<DType>?*?phead?=?this->phead;
280????Node<DType>?*?q?=?nullptr;?//防止那啥,野指针
281????phead?=?phead->pnext;//保留头节点
282????while?(phead?!=?nullptr)
283????{
284????????q?=?phead;
285????????phead?=?phead->pnext;
286????????delete?q;?//释放
287????}
288????this->phead->pnext?=?nullptr;
289????return?OK;
290}
291//销毁链表(all?delete)
292template?<typename?DType>
293status?CSingleLinkList<DType>::DestorySList()
294{
295????ClearSList();
296????delete?this->phead;//释放头结点?
297????return?OK;
298}
299
300template?<typename?DType>
301status?CSingleLinkList<DType>::DeleteSListNodeBack()
302{
303????Node<DType>?*?phead?=?this->phead;
304????Node<DType>?*?q?=?nullptr;?//备用
305????if?(phead->pnext?==?nullptr)
306????{
307????????return?ERROR;?//链表都空了还删鸡毛
308????}
309????while?(phead->pnext?!=?nullptr)
310????{
311????????q?=?phead;
312????????phead?=?phead->pnext;
313????}
314????q->pnext?=?nullptr;
315????delete?phead;
316
317????return?OK;
318
319}
320template?<typename?DType>
321void?CSingleLinkList<DType>::PrintSList()
322{
323????Node<DType>?*?phead?=?this->phead;
324????if?(phead->pnext?==?nullptr?||?phead?==?nullptr)
325????{
326????????cout?<<?"链表为空,打印鸡毛"?<<?endl;
327????????return;
328????}
329????int?i?=?1;
330????cout?<<?"===============print?list================"?<<?endl;
331????while?(phead->pnext?!=?nullptr)
332????{
333????????phead?=?phead->pnext;
334????????cout?<<"node["?<<?i++?<<?"]?=?"?<<?phead->data<<endl;
335????}
336}
337
338/*
339?*?文件名:SingleLinkListTest.cpp
340?*?说明?:测试代码
341?*/
342
343?#include?<iostream>
344#include?"SingleLinkList.h"
345#include?"SingleLinkList.cpp"
346
347using?namespace?std;
348
349int?main()
350{
351????CSingleLinkList<int>?*?pMySList?=?new?CSingleLinkList<int>;
352????cout?<<?pMySList->IsSListEmpty()?<<?endl;
353????pMySList->AddSListNodeFront(111);
354????pMySList->AddSListNodeFront(222);
355????pMySList->AddSListNodeFront(333);
356
357????cout?<<?"链表长度"?<<?pMySList->GetSListLength()?<<?endl;
358
359????pMySList->PrintSList();
360
361????pMySList->AddSListNodeBack(444);
362????pMySList->AddSListNodeBack(555);
363????pMySList->AddSListNodeBack(666);
364
365????pMySList->PrintSList();
366
367????cout?<<?pMySList->IsSListEmpty()?<<?endl;
368????cout?<<?"链表长度"?<<?pMySList->GetSListLength()?<<?endl;
369
370????int?GetElem,?GetIndex;
371????pMySList->GetSListIndexNode(&GetElem,?2);
372????cout?<<?"Got?Elem?=?"?<<?GetElem?<<?endl;
373
374????pMySList->GetSListIndexNode(&GetElem,?6);
375????cout?<<?"Got?Elem?=?"?<<?GetElem?<<?endl;
376
377????pMySList->GetSListIndexNode(&GetElem,?4);
378????cout?<<?"Got?Elem?=?"?<<?GetElem?<<?endl;
379
380????pMySList->DeleteSListIndexNode(&GetElem,?1);
381????cout?<<?"del?Elem?=?"?<<?GetElem?<<?endl;
382????pMySList->DeleteSListIndexNode(&GetElem,?3);
383????cout?<<?"del?Elem?=?"?<<?GetElem?<<?endl;
384
385
386????pMySList->PrintSList();
387
388????pMySList->SearchSListNode(555,?&GetIndex);
389????cout?<<?"Search?Index?=?"?<<?GetIndex?<<?endl;
390????pMySList->SearchSListNode(111,?&GetIndex);
391????cout?<<?"Search?Index?=?"?<<?GetIndex?<<?endl;
392????pMySList->SearchSListNode(666,?&GetIndex);
393????cout?<<?"Search?Index?=?"?<<?GetIndex?<<?endl;
394
395????pMySList->InsertSListNodeFront(333,?1);
396????pMySList->InsertSListNodeFront(444,?4);
397
398????pMySList->PrintSList();
399
400????pMySList->InsertSListNodeBack(777,?3);
401????pMySList->InsertSListNodeBack(888,?5);
402
403????pMySList->PrintSList();
404
405????pMySList->DeleteSListNodeBack();
406????pMySList->PrintSList();
407????pMySList->DeleteSListNodeBack();
408????pMySList->PrintSList();
409????pMySList->DeleteSListNodeBack();
410????pMySList->PrintSList();
411
412????return?0;
413}
414
415

代码如果有不正确的地方,欢迎大家来指正哈。

02 静态链表(circular linked list)

2.1 什么是静态链表?

我们把线性表的元素存放在数组中,这些元素由两个域组成:

  • 数据域data
  • 指针域cur

数据域是存放数据的,而指针域,这里和链表不同是,它存的不再是指向下一个节点的内存地址。而是下一个节点在数组中的下标。我们就把这种用数组描述的链表称为静态表,该方法也称之为游标实现法。如下图所示:

【数据结构】单链表amp;amp;静态链表详解和代码实例

由上图我们需要注意以下几点:

  • 我们对数组的第一个元素和最后一个元素做特殊处理,不存放数据。
  • 把未使用的数组元素称为备用链表。
  • 数组的第一个元素(下标为0)的cur域存放备用链表第一个节点的下标。
  • 数组的最后一个元素的cur域存放第一个有数据的节点的下标,相当于链表中头结点的存在。链表为空时,其值为0。

如下图:

【数据结构】单链表amp;amp;静态链表详解和代码实例

引出的问题:数组的长度定义的问题,无法预支。所以,为了防止溢出,我们一般将静态表开得大一点。

2.2 静态链表存储的代码描述

基于上面的讲解,我们来看看代码是怎么描述这种存储结构的。

1//---------线性表的静态单链表存储结构--------
2#define?MAXSIZE?1000?/*假设链表最大长度为1000*/
3typedef?struct
4{
5????datatype?data;
6????int?cur;???//为0时表示无指向
7}SLinkList[MAXSIZE];

接下来我们讲解几个重要的操作实现。

2.3 静态链表的插入操作

前面我们讲动态链表的时候说过,增加和删除一个节点我们可以用malloc()和free()函数(C++可用new和delete)来实现。但是现在由于我们操作的是静态表,它可是用数组存的,可没有这种操作了。因此我们首先来自己实现一个静态表的malloc和free。

那么怎么辨别数组中哪些空间没有被使用呢?一个好的解决办法是,将所有未使用或者被删除的空间串成一个备用链表。插入节点时便可以从备用链表获取第一个未使用的空间的下标。因此我们在初始化的时候会做这样的工作:

 1void?SListInit(SLinkList?space)
2{
3????int?i;
4????for(i?=?0;?i?<?MAXSIZE;?i++)
5????????space[i].cur?=?i+1;?//将所有结点链入备用链表
6????//备用链表头指针链像第二个结点
7????space[0].cur?=?space[1].cur;?
8????//第一个结点作为链表的头结点??
9????space[1].cur?=?0;??????????????
10}

分配内存

 1/分配备用链表的一个结点,返回下标
2//若为0,则说明备用链表用完
3int?Malloc_SL(SLinkList?space)
4{
5????int?i?=?space[0].cur;
6????//判断备用链表是否非空
7????if(space[0].cur)????
8????????//备用链表头指针指向第二个空结点
9????????space[0].cur?=?space[i].cur;?
10
11????return?i;????//返回第一个空结点
12}

上面的代码应该是没有难度的。写完了这个函数,我们来看看静态表中具体如何插入:

 1//在链表的第i个位置插入元素e
2void?SlistInsert(SLinkList?space,?int?i,?ElemType?e)
3{
4????//超出范围
5????if(i?<?1?||?i?>?SListLength(space)+1)?
6????????return;
7????int?k?=?1,?j;
8????//使k指示要插入的结点的前一个结点
9????for(j?=?0;?j?<i-1;?j++)?
10????????k?=?space[k].cur;
11
12????int?v?=?Malloc_SL(space);
13????if(v)?????//如果有空间
14????{
15????????space[v].data?=?e;
16????????space[v].cur?=?space[k].cur;
17????????space[k].cur?=?v;??//链入链表
18????}
19}

注意几点:

  • 首先我们让k指向了要插入节点(记为X)的前一个位置(记为Y节点),前插法。
  • 然后我们在静态表内申请空间,存放新的节点(记为N)。
  • 把数据放进新申请的节点里面。
  • 新节点N的cur域指向X节点,然后让Y节点指向N节点。

该过程不难理解。就不上图了……

2.4 静态链表的删除操作

删除同样需要自己实现free函数,我们来看看代码:

回收内存

1//将下标为k的空闲结点回收到备用链表
2void?Free_SL(SLinkList?space,?int?k)
3{
4????//将备用链表链到k之后
5????space[k].cur?=?space[0].cur;??
6????//将k链到备用链表头之后
7????space[0].cur?=?k;???????????????
8}

删除以后记得把空间重新挂载到备用链表上以便下一次使用。下面我们实现删除的代码:

 1//删除第i个位置的元素
2void?SListDelete(SLinkList?space,?int?i)
3{???//超出范围退出
4????if(i?<?1?||?i?>?SListLength(space))??
5????????return?;
6????int?k?=?1,?j;
7?????//使k指示要删除的结点的前一个结点
8????for(j?=?0;?j?<i-1;?j++)??
9????????k?=?space[k].cur;
10
11????int?temp?=?space[k].cur;
12????space[k].cur?=?space[temp].cur;
13????Free_SL(space,?temp);
14}

其实代码也很好理解了。假如X、Y、Z……等等排列,我们要删除Y。无非就是告诉X,你不要指向Y了,你直接指向Z,然后我们再把Y给free了。就直接变成了X、Z……简单吧。

2.5 静态链表的完整代码

熬了一个下午,终于写完了.哈哈,用了C++的类模板封装了一个静态链表,简单的增删查改功能都有了.具体可以看代码:

StaticLinkList.h

 1#pragma?once
2#include?<iomanip>
3
4#define?MAXSIZE?100
5
6#define?status?bool
7#define?YES?true
8#define?NO?false
9#define?OK?true
10#define?ERROR?false
11
12template?<typename?DATATYPE>
13class?Component
14{
15public:
16????DATATYPE?data;?//数据域
17????int?cur;???????//cur域,指向下一个元素的下标
18};
19
20
21template?<typename?DATATYPE>
22class?CStaticLinkList
23{
24public:
25????Component<DATATYPE>??StaticLinkList[MAXSIZE];??//静态表
26//自定义malloc和free
27public:
28????int?MallocNodeSSL();
29????status?FreeNodeSSL(int?index);
30public:
31????status?InitList();?//初始化静态表
32????status?BackAddList(?DATATYPE?AddData);?//尾增加
33????status?InsertNodeList(DATATYPE?InsertData,?int?index);//指定位置插入
34????status?DeleteNodeList(DATATYPE?*DelData,?int?index);?//指定位置删除
35????int?SearchList(DATATYPE?sData);???????//搜索数据为sData的节点,返回其在数组中的下标,0表示失败
36????status?GetIndexList(DATATYPE?*gData,?int?index);//获取指定索引的节点数据
37????int?GetLengthList();?//获取静态表的长度
38????status?ClearList();?//清空静态表
39????status?IsEmptyList();?//判断静态表是否为空
40????status?IsFullList();?//判断静态表是否满了
41????void?PrintList();?//打印静态表,此函数根据实际情况编写
42
43public:
44????CStaticLinkList();
45????~CStaticLinkList();
46};

StaticLinkList.cpp

 1#include?"StaticLinkList.h"
2
3template?<typename?DATATYPE>
4CStaticLinkList<DATATYPE>::CStaticLinkList()
5{
6????cout?<<?"===========静态表创建==========="?<<?endl;
7????InitList();
8}
9
10template?<typename?DATATYPE>
11CStaticLinkList<DATATYPE>::~CStaticLinkList()
12{
13????cout?<<?"===========静态表销毁==========="?<<?endl;
14}
15
16template?<typename?DATATYPE>
17int?CStaticLinkList<DATATYPE>::MallocNodeSSL()
18{
19????int?index?=?StaticLinkList[0].cur;?//把备用链表第一个节点拿出来用
20????if?(StaticLinkList[0].cur)?//判断是否还有位置
21????{
22????????StaticLinkList[0].cur?=?StaticLinkList[index].cur;?//让备用链表第二个节点上来顶替第一个的位置
23????}
24
25????return?index;?//返回0表示分配失败
26}
27
28template?<typename?DATATYPE>
29status?CStaticLinkList<DATATYPE>::FreeNodeSSL(int?index)
30{
31????//将删除节点挂接到备用链表上
32????this->StaticLinkList[index].cur?=?this->StaticLinkList[0].cur;
33????this->StaticLinkList[0].cur?=?index;
34
35????return?OK;
36}
37
38template?<typename?DATATYPE>
39status?CStaticLinkList<DATATYPE>::InitList()
40{
41????int?i;
42????for?(i?=?0;?i?<?MAXSIZE?-?1;?i++)
43????{
44????????StaticLinkList[i].cur?=?i?+?1;//全部塞入备用链表
45????}
46????StaticLinkList[MAXSIZE?-?1].cur?=?0;/*因为目前静态表为空,最后一个节点的cur域为0*/
47????return?OK;
48}
49
50template?<typename?DATATYPE>
51status?CStaticLinkList<DATATYPE>::BackAddList(DATATYPE?AddData)?//尾增加
52{
53????if?(IsFullList())
54????{
55????????return?ERROR;
56????}
57????int?index?=?MAXSIZE?-?1;
58????int?last?=?index;
59
60????while?(index?!=?0)
61????{
62????????last?=?index;
63????????index?=?StaticLinkList[index].cur;
64????}
65
66????int?k?=?MallocNodeSSL();?//获取空闲位置下标
67????if?(k)
68????{
69????????StaticLinkList[k].data?=?AddData;?//存入数据
70????????StaticLinkList[k].cur?=?0;???//末尾指向0
71????????StaticLinkList[last].cur?=?k;
72????????return?OK;
73????}
74
75????return?ERROR;
76
77}
78//在List中第i个节点之前插入新的节点
79template?<typename?DATATYPE>
80status?CStaticLinkList<DATATYPE>::InsertNodeList(DATATYPE?InsertData,?int?index)//指定位置插入
81{
82????int?i,?GetFree,?pos;
83????pos?=?MAXSIZE?-?1;//最后节点下标
84????if?(index?<?1?||?index?>?GetLengthList()?||?IsFullList())
85????{
86????????return?ERROR;?//位置异常处理
87????}
88
89????GetFree?=?MallocNodeSSL();
90????if?(GetFree)
91????{
92????????StaticLinkList[GetFree].data?=?InsertData;
93????????for?(i?=?0;?i?<?index?-?1;?i++)
94????????{
95????????????pos?=?StaticLinkList[pos].cur;?//定位
96????????}
97????????StaticLinkList[GetFree].cur?=?StaticLinkList[pos].cur;
98????????StaticLinkList[pos].cur?=?GetFree;?//插入
99
100????????int?q?=?StaticLinkList[MAXSIZE?-?1].cur;
101????????if?(q?==?0)?//静态表为空
102????????{
103????????????StaticLinkList[MAXSIZE?-?1].cur?=?1;
104????????}
105????????return?OK;
106????}
107????return?ERROR;
108}
109
110//判断是否为空
111template?<typename?DATATYPE>
112status?CStaticLinkList<DATATYPE>::IsEmptyList()
113{
114????if?(StaticLinkList[MAXSIZE-1].cur?==?0)
115????{
116????????return?YES;?
117????}
118
119????return?NO;
120}
121//判断静态表是否满了
122template?<typename?DATATYPE>
123status?CStaticLinkList<DATATYPE>::IsFullList()
124{
125????if?(GetLengthList()?==?MAXSIZE?-?2)?//因为首位不存数据,因此pass掉
126????{
127????????return?YES;
128????}
129????return?NO;
130}
131template?<typename?DATATYPE>
132int?CStaticLinkList<DATATYPE>::GetLengthList()?//获取静态表的长度
133{
134????int?iCount?=?0;
135????int?k?=?MAXSIZE?-?1;
136????while?(StaticLinkList[k].cur?!=?0)
137????{
138????????iCount++;
139????????k?=?StaticLinkList[k].cur;
140????}
141
142????return?iCount;
143}
144template?<typename?DATATYPE>
145status?CStaticLinkList<DATATYPE>::DeleteNodeList(DATATYPE?*DelData,?int?index)//指定位置删除
146{
147????int?i,?pos,?k;
148????pos?=?MAXSIZE?-?1;//最后节点下标
149????if?(index?<?1?||?index?>?GetLengthList()?||?IsEmptyList())
150????{
151????????return?ERROR;?//位置异常处理
152????}
153????for?(i?=?0;?i?<?index?-?1;?i++)
154????{
155????????pos?=?StaticLinkList[pos].cur;?//定位到被删除节点的前一个节点
156????}
157????k?=?StaticLinkList[pos].cur;?
158????*DelData?=?StaticLinkList[k].data;?//获取数据
159????StaticLinkList[pos].cur?=?StaticLinkList[k].cur;//让前一个节点直接指向后一个节点.把夹在中间的踢掉
160????FreeNodeSSL(k);?//释放空间
161
162????return?OK;
163}
164//搜索数据为sData的节点,返回其在静态表中的第i个位置,0表示没找到
165template?<typename?DATATYPE>
166int?CStaticLinkList<DATATYPE>::SearchList(DATATYPE?sData)
167{
168????int?pos?=?StaticLinkList[MAXSIZE-1].cur;
169????int?iCount?=?1;
170????while?(pos?!=?0)
171????{
172????????if?(StaticLinkList[pos].data?==?sData)?//找到数据
173????????{
174????????????return?iCount;
175????????}
176????????pos?=?StaticLinkList[pos].cur;?//循环遍历
177????????iCount++;
178????}
179
180????return?0;
181}
182template?<typename?DATATYPE>
183status?CStaticLinkList<DATATYPE>::GetIndexList(DATATYPE?*gData,?int?index)//获取第index个节点数据
184{
185????int?i,?pos;
186????pos?=?MAXSIZE?-?1;//最后节点下标
187????if?(index?<?1?||?index?>?GetLengthList()?||?IsEmptyList())
188????{
189????????return?ERROR;?//位置异常处理
190????}
191????for?(i?=?0;?i?<?index;?i++)
192????{
193????????pos?=?StaticLinkList[pos].cur;?//定位到第index个节点
194????}
195????*gData?=?StaticLinkList[pos].data;
196
197????return?OK;
198}
199template?<typename?DATATYPE>
200status??CStaticLinkList<DATATYPE>::ClearList()?//清空静态表
201{
202????InitList();//再初始化一次就是清空了
203????return??OK;
204}
205template?<typename?DATATYPE>
206void??CStaticLinkList<DATATYPE>::PrintList()
207{
208????int?pos?=?StaticLinkList[MAXSIZE?-?1].cur;
209????if?(pos?==?0)
210????{
211????????cout?<<?"===========静态链表为空,打印鸡毛!!!==========="?<<?endl;
212????????return;
213????}
214????cout?<<?setiosflags(ios::left);
215????cout?<<?setw(10)?<<?"索引"?<<?setw(10)?<<?"下标"?<<?setw(10)?<<?"data"?<<?setw(10)?<<?"cur"?<<?endl;
216????int?iCount?=?1;
217????while?(pos?!=?0)
218????{
219????????cout?<<?setw(10)?<<?iCount?<<?setw(10)?<<?pos?<<?setw(10)?<<?StaticLinkList[pos].data?<<?setw(10)?<<?StaticLinkList[pos].cur?<<?endl;
220????????pos?=?StaticLinkList[pos].cur;?//循环遍历
221????????iCount++;
222????}
223}

StaticLinkListTest.cpp测试代码

 1#include?<iostream>
2#include?<iomanip>
3#include?"StaticLinkList.h"
4#include?"StaticLinkList.cpp"
5using?namespace?std;
6
7int?main()
8{
9????char?get;
10????CStaticLinkList<char>?*p?=?new?CStaticLinkList<char>;
11????p->PrintList();
12
13????p->BackAddList(‘a‘);?//pass
14????p->BackAddList(‘b‘);
15????p->BackAddList(‘c‘);
16????p->BackAddList(‘d‘);
17????p->BackAddList(‘e‘);
18
19????//p->ClearList();??????//pass
20
21????p->PrintList();
22
23????p->DeleteNodeList(&get,?2);??//pass
24????cout?<<?"get?=?"?<<?get?<<?endl;
25
26????p->DeleteNodeList(&get,?2);
27????cout?<<?"get?=?"?<<?get?<<?endl;
28
29????p->PrintList();
30????p->BackAddList(‘f‘);
31
32????p->PrintList();
33????cout?<<?"length?=?"?<<?p->GetLengthList()?<<?endl;//pass
34
35????p->GetIndexList(&get,?3);??//pass
36????cout?<<?"get?=?"?<<?get?<<?endl;?
37
38????p->InsertNodeList(‘h‘,?2);
39????p->InsertNodeList(‘i‘,?3);
40
41????p->PrintList();
42????cout?<<?"length?=?"?<<?p->GetLengthList()?<<?endl;//pass
43
44????cout?<<?"search_pos?=?"?<<?p->SearchList(‘q‘)?<<?endl;
45????cout?<<?"search_pos?=?"?<<?p->SearchList(‘h‘)?<<?endl;
46????cout?<<?"search_pos?=?"?<<?p->SearchList(‘i‘)?<<?endl;
47
48????delete?p;
49
50????return?0;
51}

运行结果

【数据结构】单链表amp;amp;静态链表详解和代码实例

运行结果

代码未经过严谨测试,如果有错,欢迎大家指正和交流啊.

这次就先到这里吧。更多精彩内容,请期待下回分解。

(编辑:ASP站长网)

    网友评论
    推荐文章
      热点阅读