一、双向链表
在每个结点中多增加一个前驱指针,指向前一个元素
(为空表时前驱指针和后继指针都指向NULL)
1、定义双向链表的结构体(用于存储其数据的数据类型)
typedef int Elemtype;
typedef struct DuLNode { //定义一个新的数据类型
Elemtype data;
struct DuLNode* prior, * next; //定义与该结构体相同的数据类型的一个用于指向前一个结点的指针
//另一个用于指向后一个结点的指针
}DuLNode,*DuLinkList;
//代码中的 Elemtype是自己定义的数据类型可根据要存储的数据自己定义声明,例子中则是int
而整个结构体则是因为链表所需要存储的数据要多个不同数据类型,因此采用结构体的形式将其定义在结构体中,所以可以将结构同样看成一个数据类型(内部包含多个数据类型)
而双向链表则在链表的基础上增加了一个指向前一个结点的指针
插入
void ListInsert(DuLinkList& L, int i, Elemtype e) {
if(!p=Get(L,i)) //Get(L,i)为找根据所给位置找寻对应的结点的函数
printf("输入位置错误");
s = new DuLNode; //创建一个新的结点
s->data=e; //将要插入的值赋给新创建的结点的数据域
s->prior = p->prior //将要插入的结点的前驱指针指向要插入位置原来结点的前一个结点
p->prior->next = s //使要插入位置的原来结点的前一个结点指向要插入结点
s->next = p; //将要插入结点的后继指针指向要插入位置的原来结点
p->prior = s; //使要插入位置的原来结点的前驱指针指向插入的结点
}
代码中的DuLinkList为创建L链表的结构体类型(可根据自身存储数据要求自行定义)
2、删除
void ListDelete(DuLinkList& L, int i) {
if (!p = Get(L, i)) return ERROR; //用来查找要删除的元素位置判断是否合法
p->prior->next = p->next; //将要删除的结点的前一个结点的后继指针指向要删除结点的后一个结点
p->next->prior = p->prior; //使将要删除的结点的后一个结点的前驱指针指向要删除的结点的前一个
free(p); //释放要删除的结点的存储空间 结点
}
二、循环链表
即最后一个结点的指针域不再指向空而是指向头结点形成一个环
(为空表时首元结点指针域指向自身)
其优点:从表中任一结点出发均可找到其他结点不用再局限于只能从头结点开始查找
1、循环链表的结构体定义和其他功能与链表大致相同,不同之处在于其初始化时尾指针(最后一个元素的指针)是指向头结点的再将两者置空完成初始化。
2、两个循环链表的合并
LinkList Connect(LinkList Ta, LinkList Tb) {
p = Ta->next; //将表Ta中的头结点存入p指针中
Ta->next = Tb->next->next; //将Ta的尾指针指向Tb的首元结点
delete Tb->next; //释放Tb的头结点
Tb->next = p; //将Tb的尾指针指向Ta表的头结点
return Tb; //返回合并后的链表
}
代码中的LinkList 为事先根据存储数据需要自己定义的结构体的名字(代码中未展示)
Ta和Tb为两个链表。
三、双向循环链表
结合了双向链表和循环链表的特性,一个结点中存在着两个结点,一个指向前驱一个指向后继
再就是头结点的前驱指向最后一个结点,最后一个结点的后继指向头结点,形成双向循环