双链表的基本操作---插入,删除,交,并,相邻元素的交换,不相邻元素的交换...

这个链表是带有表头的双链表。实现链表的一些规范操作,初始化,插入,删除等。包括两个头文件list.h,fatal.h,库函数list.c,测试函数testlist.c。头文件放的都是函数声明,库函数list.c放的的函数的定义。

头文件list.h

 1 typedef int ElementType;
 2 #ifndef _List_H
 3 struct Node;
 4 typedef struct Node *PtrToNode;
 5 typedef PtrToNode List;
 6 typedef PtrToNode Position;
 7 #include<stdbool.h>
 8 List MakeEmpty(List L);
 9 void DeleteList(List L);
10 bool IsEmpty(List L);
11 bool IsLast(Position P, List L);
12 Position Find(ElementType X, List L);
13 void Delete(ElementType X, List L);
14 void Insert(ElementType X, List L,Position P);
15 Position Header(List L);
16 Position First(List L);
17 Position Advance(Position P);
18 Position Front(Position P);
19 ElementType Retrieve(Position P);
20 void PrintList(const List L);
21 void PrintLots(List L, List P);
22 void SwapWithNext(Position P, List L);
23 void SwapWithNoNext(Position P1,Position P2, List L);
24 List IntersectList(List L, List P);
25 List UnionList(Position L, Position P);
26 #endif // !_List_H

头文件fatal.h:

1 #include<stdio.h>
2 #include<stdlib.h>
3 #define Error(Str) FatalError(Str)
4 #define FatalError(Str) fprintf(stderr,"%s\n",Str),exit(1);

 库函数list.c:

//引用头文件
#include "list.h"
#include<stdlib.h>
#include "fatal.h"//结构体定义,一个前指针Pre和一个后指针Next
struct Node
{ElementType Element;Position Next;Position Prev;
};//初始化链表
List MakeEmpty(List L)
{if (L != NULL)DeleteList(L);L = malloc(sizeof(struct Node));if (L == NULL)FatalError("Out of memory!");L->Next = NULL;L->Prev = L;return L;
}//删除链表
void DeleteList(List L)
{Position P, Temp;P = L->Next;L->Next = NULL;while (P != NULL){Temp = P->Next;free(P);P = Temp;}
}//判断链表是否为空
bool IsEmpty(List L)
{return L->Next == NULL;
}//判断当前指针P是否指向链表最后一个元素
bool IsLast(Position P, List L)
{return P->Next == NULL;
}//在链表中找元素X,如果返回是NULL说明没找到
Position Find(ElementType X, List L)
{Position P;P = L->Next;while (P != NULL && P->Element != X)P = P->Next;return P;
}//删除链表中的元素X,若返回NULL,说明在链表中没找到元素X
void Delete(ElementType X, List L)
{Position P;P = Find(X, L);//if P==NULL,说明没找到if (P != NULL)//当P不是空指针,说明找到了
    {if (!IsLast(P, L)){P->Prev->Next = P->Next;P->Next->Prev = P->Prev;free(P);}else //最后一个结点特殊处理,最后一个结点p->next无prev
        {P->Prev->Next = NULL;free(P);}}}//插入元素X到位置P后面
void Insert(ElementType X, List L, Position P)
{Position  TmpCell;TmpCell = malloc(sizeof(struct Node));if (TmpCell == NULL)FatalError("Out of Space!!!");TmpCell->Element = X;TmpCell->Next = P->Next;P->Next = TmpCell;TmpCell->Prev = P;
}//获取链表头
Position Header(List L)
{return L;
}//获取链表第一个元素的位置
Position First(List L)
{return L->Next;
}//获取位置P的下(后)一个位置
Position Advance(Position P)
{return P->Next;
}//获取位置P的上(前)一个位置
Position Front(Position P)
{return P->Prev;
}//提取位置P处结构里面的值
ElementType Retrieve(Position P)
{return P->Element;
}//打印链表
void PrintList(const List L)
{Position P = Header(L);if (IsEmpty(L))printf("Empty list\n");else{do{P = Advance(P);printf("%d ", Retrieve(P));} while (!IsLast(P, L));printf("\n");}
}//打印链表L中那些由P所指定的位置上的元素。例如P=1,3,4,6,将L
//中的第1,第3,第4,第6个元素打印出来
void PrintLots(List L, List P)
{int count = 1;Position Lpos, Ppos;Lpos = First(L);Ppos = First(P);while (Lpos != NULL&&Ppos != NULL){if (Ppos->Element == count++){printf("%d ", Ppos->Element);Ppos = Advance(Ppos);}Lpos = Advance(Lpos);}}//通过只调整指针来交换两个相邻的元素,P是要调换两个元素中的前一
//个指针
void SwapWithNext(Position P, List L)
{Position AfterP;//AfterP是后一个指针if (P != NULL){AfterP = Advance(P);if (AfterP != NULL)//下面总共六条语句动六根线(除去if),
//前两条动P的一个节点,接下来两条语句动AfterP的后一个节点,最后两条
//语句动P和AfterP两个节点
        {P->Prev->Next = AfterP;//先调换P的前一个节点的
//next,让它指向AfterPAfterP->Prev = P->Prev;//再让AfterP的前节点指向P
//的前一个节点,这样P的前一个节点就指向好了if (Advance(AfterP) != NULL)//为了防止After是尾指
//针,如果After是尾指针,则AfterP->Next=NULL,没有前节点,就什么
//都不做AfterP->Next->Prev = P; // 让AfterP的后一个
//节点的前节点改为指向P;P->Next = AfterP->Next;//P的Next指向AfterP的下一
//个节点AfterP->Next = P;//AfterP的下一个节点指向P;P->Prev = AfterP;//P的前节点指向After;
        }}
}//通过只调整指针来交换两个不相邻的元素p1和p2
void SwapWithNoNext(Position P1, Position P2, List L)//p1在前,p2
//在后
{Position P1f, P1b, P2f, P2b;//构造四个中间变量,清晰P1f = P1->Prev;P1b = P1->Next;P2f = P2->Prev;P2b = P2->Next;//八条语句P1f->Next = P2;P2->Prev = P1f;P2->Next = P1b;P1b->Prev = P2;P2f->Next = P1;P1->Prev = P2f;P1->Next = P2b;if (P2b!=NULL)//如果P2b=NULL,就没有前指针PrevP2b->Prev = P1;
}//求两个链表的交集
List IntersectList(List L1, List L2)
{List ResultList;Position L1Pos, L2Pos, ResultPos;ResultList = MakeEmpty(NULL);L1Pos = First(L1);L2Pos = First(L2);ResultPos = Header(ResultList);while (L1Pos != NULL&&L2Pos != NULL){if (L1Pos->Element < L2Pos->Element)L1Pos = Advance(L1Pos);else if (L1Pos->Element > L2Pos->Element)L2Pos = Advance(L2Pos);else{Insert(L1Pos->Element, ResultList, ResultPos);ResultPos = Advance(ResultPos);L1Pos = Advance(L1Pos);L2Pos = Advance(L2Pos);}}return ResultList;
}//求两个链表的并集
List UnionList(Position L1, Position L2)
{List ResultList;ElementType InsertElement;Position L1Pos, L2Pos, ResultPos;ResultList = MakeEmpty(NULL);L1Pos = First(L1);L2Pos = First(L2);ResultPos = Header(ResultList);while (L1Pos != NULL&&L2Pos != NULL){if (L1Pos->Element < L2Pos->Element){InsertElement = L1Pos->Element;L1Pos = Advance(L1Pos);}else if (L1Pos->Element > L2Pos->Element){InsertElement = L2Pos->Element;L2Pos = Advance(L2Pos);}else{InsertElement = L1Pos->Element;L1Pos = Advance(L1Pos);L2Pos = Advance(L2Pos);}Insert(InsertElement, ResultList, ResultPos);ResultPos = Advance(ResultPos);}while (L1Pos != NULL){Insert(L1Pos->Element, ResultList, ResultPos);ResultPos = Advance(ResultPos);L1Pos = Advance(L1Pos);}while (L2Pos != NULL){Insert(L2Pos->Element, ResultList, ResultPos);ResultPos = Advance(ResultPos);L2Pos = Advance(L2Pos);}return ResultList;
}

 测试函数testlist.c

 1 #include<stdio.h>
 2 #include "list.h"
 3 main()
 4 {
 5     List L,L1;
 6     Position P,P1;
 7     int i;
 8     L = MakeEmpty(NULL);
 9     P = Header(L);
10     PrintList(L);
11 
12     L1 = MakeEmpty(NULL);
13     P1 = Header(L1);
14     PrintList(L1);
15 
16 
17     for (i = 0; i < 50; i+=1)
18     {
19         Insert(i, L, P);
20         //PrintList(L);
21         P = Advance(P);
22     }
23     PrintList(L);
24     printf("\n");
25     for (i = 1; i < 100; i+=3)
26     {
27         Insert(i, L1, P1);
28         //PrintList(L);
29         P1 = Advance(P1);
30     }
31     PrintList(L1);
32     printf("\n");
33 
34     PrintList(IntersectList(L, L1));
35     printf("\n");
36     PrintList(UnionList(L, L1));
37     //PrintLots(L, L1);
38 
39     //SwapWithNext(Advance(Advance(Advance(L))),L);//换头两个元素
40     //SwapWithNoNext(Advance(L), Advance(Advance(Advance(Advance(L)))),L);
41     //for (i = 0; i < 10; i += 2)
42     //    Delete(i, L);
43     //for (i = 0; i < 10; i++)
44     //{
45     //    if ((i % 2 == 0) == (Find(i, L) != NULL))
46     //        printf("Find fails\n");
47     //}
48     //printf("Finished deletions\n");
49     //PrintList(L);
50     DeleteList(L);
51     DeleteList(L1);
52     return 0;
53 }

转载于:https://www.cnblogs.com/xinlovedai/p/6216160.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/270252.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手机选购:2022年初买手机多大内存合适,看完你就会选了!

2022年初&#xff0c;大家又要开始换手机了&#xff0c;除了考虑品牌、价位之外&#xff0c;大家还要纠结手机内存大小&#xff0c;128GB、256GB和512GB三个版本是目前的主流选择&#xff0c;那么这三个版本应该如何选择呢&#xff1f;其实关于手机内存的大小选择&#xff0c;没…

SSD是什么什么意思?

SSD是什么什么意思? 固态存储技术简称为SSD&#xff0c;一般可以分为二种方式&#xff1a;   基于闪存的SSD&#xff1a;采用FLASH芯片作为存储介质&#xff0c;这也是通常所说的SSD。它的外观可以被制作成多种摸样&#xff0c;例如&#xff1a;笔记本硬盘、微硬盘、存储卡、…

2010年安大计算机录取名单,2021安徽大学考研拟录取名单已公布

当前2021考研已接近尾声&#xff0c;各大研招院校已进入2021考研复试调剂收尾阶段&#xff0c;考研复试拟录取名单正在陆续公布中。拟录取表示已经复试合格&#xff0c;等待正式录取。研究生拟录取后&#xff0c;要经教育部审查通过后才能正式录取&#xff0c;往届生教育部要验…

debian jessie install note

Debian支持非常多的硬件&#xff0c;包括arm/mips/ppc/x86&#xff0c;于是想安装个Debian看看&#xff0c;也不想总屈服在canonical的ubuntu下面。 光盘镜像太多了 纯社区版的安装总是没有想像得那么好&#xff0c;首先安装镜像居然有3个iso&#xff0c;让我们不想刻光盘的同志…

APP技巧:要不要一次性给手机充电到100%最佳

你平时都是怎么给手机充电的呢&#xff1f;一次性把电池电量充到100%&#xff1f;直接充一夜&#xff1f;还是等到电池电量耗尽之后再充电&#xff1f; 实际上&#xff0c;你给手机充电的方式可能是错误的&#xff0c;你的充电习惯可能一直在加快电池报废的速度。 今天就和大家…

MySQL系列: undo和redo工作原理

ACID 首先来讨论事务的四大特性ACID 原子性&#xff08;Atomicity&#xff09;&#xff1a;事务作为一个整体来执行&#xff0c;要不都执行&#xff0c;要不都不执行 一致性&#xff08;Consistency&#xff09;&#xff1a;事务必须保证数据库从一个一致状态转移到另一个一致…

robomaster裁判系统服务器,2018裁判系统调试组网完全攻略

1.jpg (52.6 KB, 下载次数: 3)2018-4-15 21:49 上传接下来是几个比较容易弄混淆的点&#xff1a;主服务器程序将会同时监听机器上所有的 IP 地址&#xff0c;所以请保证机器上已经设置了 192.168.0.8 和 192.168.1.2 两个 IP &#xff1b;学生自定义数据的链路是主控板通过串口…

APP技巧:推荐6款超级实用的APP软件,赶快下载试试吧

目录 01*ONE一个 02*智能修复老照片 03*实用工具箱 04*李跳跳 05*Alook 06*CCleaner 今天小编给大家6款超级实用的App软件&#xff0c;大家赶快下载试试吧。 01*ONE一个 推荐理由&#xff1a;简约的新媒体阅读平台。 生活中往往有太多的碎片化时间&#xff0c;比如等公交、上厕…

《Note --- Unreal 4 --- Sample analyze --- StrategyGame(continue...)》

《Note --- Unreal 4 --- Sample analyze --- StrategyGame&#xff08;continue...&#xff09;》 -------------------------------------------------------------------------------------------------------------------------------------------------------------------…

Mysql快照读和当前读

快照读 读取的是记录数据的可见版本&#xff08;可能是过期的数据&#xff09;&#xff0c;不用加锁 当前读 读取的是记录数据的最新版本&#xff0c;并且当前读返回的记录都会加上锁&#xff0c;保证其他事务不会再并发的修改这条记录   概念说的比较虚&#xff0c;也不好理…

网络知识:快速了解IP地址的概念以及IPV4和IPV6的区别!

‍‍小伙伴们看到上面的机房了吗&#xff1f;成千上万台服务器他们都少不了一个小小的IP地址&#xff0c;每台服务器都配置了一个或多个IP。今天电脑学习微信公众号小编就带大家详细了解下IP地址都是什么&#xff1f;IP地址&#xff08;Internet Protocol Address&#xff09;是…

手机投屏到电视,1分钟就能学会,无需下载任何软件,太实用了

生活中&#xff0c;我们玩手机的时候经常看到一些好玩的东西&#xff0c;想分享给亲人&#xff0c;朋友们一起看&#xff0c;无奈手机屏幕太小&#xff0c;大家凑一起看不方便&#xff0c;效果也不好。 如果能把好玩的东西投屏到电视上&#xff0c;那这个问题就迎刃而解了&…

联想计算机BIOS开启Intel-vx,如何在计算机BIOS或UEFI固件中启用Intel VT-x | MOS86

现代CPU包括硬件虚拟化功能&#xff0c;可帮助加速在VirtualBox&#xff0c;VMware&#xff0c;Hyper-V和其他应用程序中创建的虚拟机。但是这些功能都是虚拟机是美好的事情。使用虚拟化应用程序&#xff0c;您可以在当前系统的窗口中运行整个虚拟机。在该虚拟机中&#xff0c;…

Linux操作系统安装字体笔记

从事Java程序员的朋友们都知道&#xff0c;大多数客户的应用都是部署在Linux操作系统的服务器上面&#xff0c;因为Linux服务器比Windows服务器成本要低、系统运行更加稳定。但它也有自己不足之处&#xff0c;比如在系统上导出pdf等文档时候&#xff0c;如果有中文字符的话&…

地磁室内导航定位

宋镖《基于惯导辅助地磁的手机室内定位系统设计》 转载于:https://www.cnblogs.com/2008nmj/p/6241917.html

mysql事务的 四个特征(ACID)

事务的 四个特征&#xff08;ACID&#xff09; 事务具有四个特征&#xff1a;原子性&#xff08; Atomicity &#xff09;、一致性&#xff08; Consistency &#xff09;、隔离性&#xff08; Isolation &#xff09;和持续性&#xff08; Durability &#xff09;。这四个特…

foxmail连接163邮箱服务器,消除Foxmail无法登录163邮箱顽疾

用手机号申请了163免费邮箱&#xff0c;在网页端或手机网易邮箱客户端可以正常登录&#xff0c;但在电脑Foxmail客户端中&#xff0c;按相同的邮件服务器进行设置&#xff0c;显示密码不正确。难道163邮箱已经不支持PC中的Foxmail客户端了吗&#xff1f;让我们一同探究解决之道…

网络知识:水晶头网线和网线插座接法制作过程介绍

今天小编给大家分享水晶头网线和网线插座的制作过程&#xff0c;有需要的朋友可以收藏一下&#xff01;家庭网线插座接法详解我们这里所说的网线插座&#xff0c;正确的叫法应该是网线模块&#xff0c;一般应用在室内的墙壁上作为网线插孔。现在家庭中使用的一般都是双绞线&…

Arduino 极速入门系列 - 光控灯(3) - 光敏电阻、与电阻分压那些事

继续是讲解基础原理&#xff0c;新手专用部分。这次讲光敏电阻&#xff0c;和用电阻分压。光电元器件有好几种&#xff0c;其中测光相关的元器件&#xff0c;常见的有光敏三极管和光敏电阻&#xff0c;我们这次光控灯用光敏电阻。在我们光控灯里面&#xff0c;将会使用它搭建出…

Mysql的四种隔离级别

Mysql的四种隔离级别 SQL标准定义了4类隔离级别&#xff0c;包括了一些具体规则&#xff0c;用来限定事务内外的哪些改变是可见的&#xff0c;哪些是不可见的。低级别的隔离级一般支持更高的并发处理&#xff0c;并拥有更低的系统开销。 Read Uncommitted&#xff08;读取未提…