超实用链表(带头节点双向循环链表)
Posted 两片空白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了超实用链表(带头节点双向循环链表)相关的知识,希望对你有一定的参考价值。
逻辑结构
物理结构
带头节点双向循环链表,有两个指针域,一个数据域。一个指针存前面一个结点的地址,一个指针存下一个结点的地址。
typedef int Datatype;
typedef struct Dlist{
Datatype data;
struct Dlist *next;
struct Dlist *pre;
}Dlist;
实现功能
Dlist *DlistCreate(Datatype x);//创建结点
Dlist *DlistInit(Datatype x);//初始化头节点
void DlistPushFront(Dlist *list, Datatype x);//头插
void DlistPopFront(Dlist *list);//头删
void DlistPushAfter(Dlist *list, Datatype x);//尾插
void DlistPopAfter(Dlist *list);//尾删
Dlist *DlistFind(Dlist *list, Datatype x);//找某一结点
void DlistInsert(Dlist *pos, Datatype x);//在pos前插
void DlistErease(Dlist *pos);//将pos删除
void DlistPrint(Dlist *list);//打印
int DlistIsEmpty(Dlist *list);//判定空
void DlistDestory(Dlist *list);//释放结点,除头节点
代码
1.创建链表头节点
Dlist *DlistCreate(Datatype x){//创建结点
Dlist *newnode = (Dlist *)malloc(sizeof(Dlist));
newnode->data = x;
newnode->next = NULL;
newnode->pre = NULL;
return newnode;
}
Dlist *DlistInit(Datatype x){//将头节点初始化,循环自己指向自己
Dlist *head = DlistCreate(x);
head->next = head;
head->pre = head;
return head;
}
2.头/尾插,在pos前插入
只有一个头节点的情况该代码也适用。
void DlistPushFront(Dlist *list, Datatype x){//头插
assert(list);
Dlist *newnode = DlistCreate(x);
Dlist *tail = list->next;
list->next = newnode;
newnode->pre = list;
newnode->next = tail;
tail->pre = newnode;
}
void DlistPushAfter(Dlist *list, Datatype x){//尾插
assert(list);
Dlist *newnode = DlistCreate(x);
Dlist *tail = list->pre;
tail->next = newnode;
newnode->next = list;
newnode->pre = tail;
list->pre = newnode;
DlistInsert(list, x);
}
void DlistInsert(Dlist *pos, Datatype x){//pos前插入,尾插相当于在list的前面插
assert(pos);
Dlist *tail = pos->pre;
Dlist *newnode = DlistCreate(x);
tail->next = newnode;
newnode->pre = tail;
newnode->next = pos;
pos->pre = newnode;
}
3.头/尾删,将pos位置删除
void DlistPopFront(Dlist *list){//头删
assert(list);
Dlist *tail = list->next;
Dlist *next = tail->next;
list->next = next;
next->pre = list;
free(tail);
}
void DlistPopAfter(Dlist *list){//尾删
assert(list);
assert(list->next != list);
Dlist *tail = list->pre;
Dlist *pre = tail->pre;
pre->next = list;
list->pre = pre;
free(tail);
DlistErease(list->pre);
}
void DlistErease(Dlist *pos){//将pos位置删除
assert(pos);
//assert(pos->next != list);
Dlist *tail = pos->pre;
Dlist *next = pos->next;
tail->next = next;
next->pre = tail;
free(pos);
}
4.找到值为X的结点
Dlist *DlistFind(Dlist *list, Datatype x){
assert(list);
Dlist *cur = list->next;//注意从头节点下一个开始
while (cur != list){
if (cur->data == x){
return cur;
}
cur = cur->next;
}
return NULL;
}
5.判端链表是否为空
int DlistIsEmpty(Dlist *list){
if (list->next == list){
return 1;
}
return 0;
}
6.销毁结点
void DlistDestory(Dlist *list){
assert(list);
Dlist *cur = list->next;
while (cur->next != list){
Dlist *next = cur->next;
free(cur);
cur = next;
}
}
验证代码
#include"Doublelist.h"
static void Test1(Dlist *list){
DlistPushFront(list, 4);
DlistPushFront(list, 3);
DlistPushFront(list, 2);
DlistPushFront(list, 1);
DlistPrint(list);
DlistPopFront(list);
DlistPopFront(list);
DlistPrint(list);
DlistPushAfter(list, 5);
DlistPushAfter(list, 6);
DlistPrint(list);
DlistPopAfter(list);
DlistPopAfter(list);
DlistPrint(list);
Dlist *pos = DlistFind(list, 4);
if (pos){
DlistInsert(pos, 40);
DlistPrint(list);
}
DlistPopAfter(list);
//DlistPopAfter(list);
//DlistPopAfter(list);
int i = DlistIsEmpty(list);
printf("%d\\n", i);
DlistDestory(list);
free(list);//释放头节点
}
int main(){
Dlist *head = DlistInit(0);
Test1(head);
system("pause");
return 0;
}
以上是关于超实用链表(带头节点双向循环链表)的主要内容,如果未能解决你的问题,请参考以下文章