数据结构C语言双向循环链表,数据结构和算法(双向链表和双向循环链表)

双向链表

双向链表也称双链表,每个数据结点都有两个指针,分别指向直接前驱和直接后继。所以从双向链表的任何结点开始都可以方便的找到他的前驱和后继。

双向链表的每个结点如图所示:

512b00f32cd0e791e01a9f547b00b07e.png

双向链表由N个此类结点构成:

数据结构C语言双向循环链表,数据结构和算法(双向链表和双向循环链表)_第1张图片

定义双向链表(C语言):包括前驱,后继,还有数据

typedef struct Node{

struct Node *prior;

Element data;

struct Node *next;

}Node;

typedef struct Node * ListNode;

复制代码

接下来,创建一个双向链表:

思路:

1.创建一个首元结点(为了方便操作,不用经常挪动头指针)

2.在链表中加入数据(单纯的为了后面的操作方便,也可以先初始化,之后再插数据)

复制代码

初始化代码如下

Status creatListNode(ListNode *L){

*L = (ListNode)malloc(sizeof(Node));

if (!(*L)) return ERROR;

(*L)->data = 0;

(*L)->prior = NULL;

(*L)->next = NULL;

//初始化这里直接增加数据,可以方便查询

ListNode p = *L;

for (int i = 0; i<5; i++) {

ListNode temp = (ListNode)malloc(sizeof(Node));

temp->next = NULL;

temp->prior = NULL;

temp->data = i;

p->next = temp;

temp->prior = p;

p = p->next;

}

return OK;

}

复制代码

为了方便操作调试,加了个打印链表的方法:

void printListNode(ListNode L){

printf("打印链表\n");

ListNode temp = L->next;

if (temp == NULL) {

printf("打印链表为空\n");

return;

}

while (temp) {

printf("%d\t",temp->data);

temp = temp->next;

}

printf("\n");

}

复制代码

下面说下插入结点:

思路:

1、首先找到插入结点的位置。

2、是不是在链表尾部(这个就直接看代码就好了)

3、temp的next指向p的next

4、p的next的prior指向temp

5、p的next指向temp

6、temp的prior指向p

如下图所示:

复制代码

数据结构C语言双向循环链表,数据结构和算法(双向链表和双向循环链表)_第2张图片

Status insertListNode(ListNode *L, int place, Element data){

ListNode p = *L;

//1. 插入的位置不合法 为0或者为负数

if(place < 1) return ERROR;

ListNode temp = (ListNode)malloc(sizeof(Node));

temp->data = data;

temp->prior = NULL;

temp->next = NULL;

//找到前驱 p

for (int i = 1;i < place && p; i++) {

p = p->next;

}

//灭有

if(p==NULL) return ERROR;

//尾部

if (p->next == NULL) {

p->next = temp;

temp->prior = p;

}else{

//插入

temp->next = p->next;

p->next->prior = temp;

temp->prior = p;

p->next = temp;

}

return OK;

}

复制代码接下来是删除代码:

老规矩--思路:

1、找到要删除位置的前一个

2、p的next指向要删除结点的next

3、删除结点的next的prior指向p

4、看下面的图(已经很生动了。。)

复制代码

数据结构C语言双向循环链表,数据结构和算法(双向链表和双向循环链表)_第3张图片

代码:

Status deleteListNode(ListNode *L, int place){

if(place < 0) return ERROR;

ListNode p = *L;

int i;

for (i = 1; i

p = p->next;

}

if (place>i || p == NULL) {

return ERROR;

}

//要删除的结点

ListNode deleTemp = p->next;

printf("要删除的值为:%d\n",deleTemp->data);

//删除

p->next = deleTemp->next;

if (deleTemp->next != NULL) {

deleTemp->next->prior = p;

}

free(deleTemp);

return OK;

}

复制代码

双向链表的查找:

思路:

简单来说就是把值传过来,然后遍历,找一样的。。

复制代码

还是直接上代码吧

Status searchListNode(ListNode L, Element data){

int j = 0;

ListNode p = L->next;

for (int i = 1;p != NULL ; i++) {

if (p->data == data) {

printf("此数值存在,位置是%d\n",i);

j = 1;

break;

}

p = p->next;

}

if (j == 0) {

printf("没有发现此数值\n");

}

return OK;

}

复制代码

给大家看下main函数:

printf("双向链表\n");

ListNode L;

Status iStatus;

int place;

Element value;

//创建双向链表

printf("创建双向链表\n");

iStatus = creatListNode(&L);

printListNode(L);

//插入

printf("输入插入元素的位置和值,中间用空格隔开\n");

scanf("%d %d",&place,&value);

iStatus = insertListNode(&L,place,value);

printListNode(L);

//删除

printf("输入删除的位置\n");

scanf("%d",&place);

iStatus = deleteListNode(&L, place);

printListNode(L);

//删除指定元素

printf("删除指定元素\n");

scanf("%d",&value);

iStatus = deleData(&L, value);

printListNode(L);

//查找

printf("查找元素\n");

scanf("%d",&value);

iStatus = searchListNode(L, value);

复制代码

控制台输出:

双向链表

创建双向链表

打印链表

01234

输入插入元素的位置和值,中间用空格隔开

1 99

打印链表

9901234

输入删除的位置

1

要删除的值为:99

打印链表

01234

删除指定元素

4

打印链表

0123

查找元素

3

此数值存在,位置是4

复制代码

ok,双向链表就告一段落了。开始双向循环链表,

双向循环链表

双向循环链表和双向链表的区别简单理解就是首尾相连了。

一个空的双向循环链表如下:c8ac52b02e8b84ce8d808a6e33380616.png

正常的双向循环链表:

数据结构C语言双向循环链表,数据结构和算法(双向链表和双向循环链表)_第4张图片

上图所示,大家应该理解双向循环链表是什么样子了。

接下来创建双向循环链表:

Status createListNode(ListNode *L){

*L = (ListNode)malloc(sizeof(Node));

if (!(*L)) return ERROR;//么有创建成功。。(这种情况基本不会存在,但是考虑代码严谨性,我还是写上了。。)

(*L)->data = 0;

(*L)->next = (*L);

(*L)->prior = (*L);

ListNode p = (*L);

//我加点数据

for (int i = 1; i < 11; i++) {

ListNode temp = (ListNode)malloc(sizeof(Node));

temp->data = i;

p->next = temp;

temp->prior = p;

temp->next = (*L);

(*L)->prior = temp;

p = p->next;

}

return OK;

}

复制代码

然后--双向循环链表的插入:

双向循环链表的插入和双向链表的插入差不多,就是要注意下首尾情况

废话我就不说了。直接上代码:

复制代码Status insertListNode(ListNode *L, int place, Element data){

//是否合法

if (place<0) return ERROR;

ListNode p = *L;

int i;

for (i = 1; p->next != *L && i < place; i++) {

p = p->next;

}

if (i > place) return ERROR;

//创建新结点

ListNode tempNode = (ListNode)malloc(sizeof(Node));

//6.temp 结点为空,则返回error

if (tempNode == NULL) return ERROR;

tempNode->data = data;

tempNode->next = p->next;

p->next->prior = tempNode;

p->next = tempNode;

tempNode->prior = p;

return OK;

}

复制代码

双向循环链表的删除

同样类似于双向链表,注意下首尾情况即可。

代码如下:

复制代码Status deleListNode(ListNode *L, int place){

int i;

ListNode p = (*L)->next;

if (*L == NULL) {

return ERROR;

}

if (p->next == (*L)) {

free(*L);

(*L) = NULL;

return OK;

}

for (i = 1; i < place; i++) {

p = p->next;

}

printf("要删除的数据是%d\n",p->data);

p->prior->next = p->next;

p->next->prior = p->prior;

free(p);

return OK;

}

复制代码为了方便调试,写了个打印方法

复制代码void printListNode(ListNode L){

printf("打印链表\n");

if (L == NULL) {

printf("双向循环链表为空!\n");

return;

}

ListNode p = L->next;

for (int i=0; p != L; i++) {

printf("%d ",p->data);

p = p->next;

}

printf("\n");

}

复制代码

main方法:

printf("双向循环链表\n");

ListNode L;

Status iStatus;

int place;

Element data;

printf("创建链表\n");

iStatus = createListNode(&L);

printListNode(L);

printf("插入位置和数据中间空格隔开\n");

scanf("%d %d",&place,&data);

iStatus = insertListNode(&L, place, data);

printListNode(L);

printf("删除数据,输入删除的位置\n");

scanf("%d",&place);

iStatus = deleListNode(&L, place);

printListNode(L);

复制代码

输出如下:

双向循环链表

创建链表

打印链表

1 2 3 4 5 6 7 8 9 10

插入位置和数据中间空格隔开

1 99

打印链表

99 1 2 3 4 5 6 7 8 9 10

删除数据,输入删除的位置

2

要删除的数据是1

打印链表

99 2 3 4 5 6 7 8 9 10

复制代码

你可能感兴趣的:(数据结构C语言双向循环链表)