CSYQ C语言数据结构之单双链表

Posted on 2019-07-07 20:26  不叫柒桓叶  阅读(226)  评论(0编辑  收藏  举报

数据结构

数据 :是对客观事物的符号的表示,在计算机科学中是指所有能够输入到计算机

中并被计算机程序处理的符号的总称

 

数据元素:数据的基本单元,在计算机程序中通常作为一个整体来进行考虑和处理

 

一个数据元素可由若干个数据项组成。数据项是数据不可分割的最小单位

 

数据对象是性质相同的数据元素的集合,是数据的子集

 

结构:数据元素之间的关系的不同特性就称为结构

根据数据元素之间的关系的不同特性,同常有以下4类基本结构

1)集合 :结构中的数据元素之间除了 “同属于一个集合”的关系外

别无其他关系

 

2)线性结构:一对一

数据元素之间的关系是线性的

 

3)树形结构:一对多

数据元素之间的关系是树状(层次)

 

4)网状结构(图)多对多

所有的数据元素之间都有可能存在关系

 

数据结构的形式定义为:数据结构是一个二元组

Data_structure = (D,S)

D 是数据元素的有限集

S D上关系的有限集

 

结构定义中 “关系”描述的是数据元素之间的逻辑关系,因此又称为数据的逻辑结构

 

数据结构在计算机中的表示又称为数据的物理结构,又称为存储结构

 

数据结构:研究的是数据本身,以及数据元素与数据元素之间的关系(逻辑关系)

 

 

1.线性表

eg

 数据元素 数据元素之间的关系

26个大写英文字母   单个字母 A必须在B的前面

 

班级人数(25,45,26,35)每个班级的人数 25必须在45的前面

 

“线性表”中的数据元素可以是各种各样的类型,但是同一个线性表中的元素必须具有相同

的特性,即属于同一数据对象,相邻数据元素之间存在着序偶关系。

 

将线性表记为:

1)存在着唯一一个称为“第一个”的数据元素

2)存在着唯一一个称为“最后一个”的数据元素

3)除第一个外,集合中的每个数据元素均有且只有一个前驱元素

4)除第一个外,集合中的每个数据元素均有且只有一个后驱元素

 

 

 

1,3,5,7,9

就是一个线性表,在计算机如何保存?

要保存什么东西?

1)数据 1 3 5 7 9

2)关系

逻辑关系

 

线性表的物理结构实现

1)顺序结构 =》数组

线性表的顺序结构指的是用一组地址连续的存储单元一次来存储线性表的数据元素

 

数据保存啦

 

int a[] = {1,3,5,7,9};

"逻辑关系"也保存

逻辑关系与物理地址关系是一致的

 

2)链式结构 =》链表

线性表的链式结构指的是不用地址连续的存储单元去保存数据元素

数据元素的存储单元不一定是连续,在保存数据元素的同时,需要

额外开辟一块空间来保存“逻辑关系”的后驱或前驱

 

 

typedef int ElemType;//表示数据元素的类型

struct node

{

ElemType data;//数据域=》保存数据

struct node*next;//关系域 =》保存逻辑上的下一个

};

 

typedef int ElemType;//表示数据元素的类型

struct node

{

ElemType data;//数据域=》保存数据

struct node*next;//关系域 =》保存逻辑上的下一个

};

 

Typedef->重新定义一个新的类型,声明了一个新的类型,原型是int

Define-> 宏定义,特点是只做替换,不做运算

Typedef int node;

Define int node;看起来结果一样

不带头结点的单链表:创建 附加代码

 

#include <stdio.h>

#include <stdlib.h>

#include "Linklist.h"

/*

Create_Linkedlist:创建一条单向无头结点链表

返回值 :返回链表的首地址

*/

struct node*Create_Linkedlist()

{

struct node*first = NULL;

struct node*last = NULL;

ElemType d;

while(1)

{

//step1:获取一个数据,就创建一个节点

scanf("%d",&d);

if(d == 0)

{

break;

}

struct node*pnew = malloc(sizeof(struct node));

//为何用malloc,是因为不会主动释放。一旦出了这个过程就变为局部变量消失了,所以一定要用malloc

//step2:把获取的数据写入到节点中

 pnew->data = d;

 pnew->next = NULL;

 

//step3:把新创建的节点加入到链表中

if(first == NULL)//从无到有

{

first = pnew;

last = pnew;

}

else//尾插法

{

last->next = pnew;//尾节点后面接新节点

last = pnew;//尾节点被新节点所替换

}

#if 0

else//头插法

{

pnew->next = first;

first = pnew;

}

#endif

}

 

return first;

}

/*

Change_node: 在链表first中,找到值为x的数据节点,将其节点的值改为y

如果有多个值为x的数据节点,修改第一个数据节点。若没有

不需要修改。将新链表返回。

返回值:新链表的首节点的地址

*/

struct node*Change_node(struct node*first,ElemType x,ElemType y)

{

struct node*p = first;//遍历指针

while(p)

{

if(p->data == x)

{

p->data = y;

break;

}

p = p->next;

}

 

return first;

}

/*

add_a_node

在链表first中,找到值为x的节点,在其前面,增加一个节点,新增加的节点

值为y,然后把新链表的首节点的地址返回。假如有多个值为x的节点,则在第一个值

x的节点前添加,如果没有值为x的节点则在最后添加

 

 

*/

struct node*add_a_node(struct node*first,ElemType x,ElemType y)

{

struct node*p = NULL;

struct node*pre = NULL;//指向p指向的节点的前一个节点

//step1:创建一个新节点,并赋值

struct node*pnew = (struct node*)malloc(sizeof(*pnew));

pnew->data = y;

pnew->next = NULL;

 

//step2:找到值为x的数据节点

p = first;

while(p)

{

if(p->data == x)

{

 

break;

}

pre = p;

p = p->next;

}

//step3:插入

if(p)// p != NULL 找到了

{

if(p == first)//x是首节点

{

pnew->next = p;

first = pnew;

}

else

{

pnew->next = p;

pre->next = pnew;

}

 

}

else//没找到

{

if(first == NULL)//该链表本身就是空链表

{

first = pnew;

}

else

{

pre->next = pnew;

}

}

 

return first;

}

/*

delete_a_node

在链表first中,找到值为x的节点,将其删除。

然后把新链表的首节点的地址返回。假如有多个值为x的节点,则删除第一个值为x的第一个节点,

如果没有值为x的节点则不删除

 

 

*/

struct node*delete_a_node(struct node*first,ElemType x)

{

struct node*p = first;//遍历指针

struct node*pre = NULL;//指向p指向的节点的前一个节点

//step1:查找值为x的节点

while(p)

{

if(p->data == x)

{

break;

}

pre = p;

p = p->next;

}

 

//step2:删除

if(p)

{

if(p == first)

{

first = first->next;

p->next = NULL;

free(p);

p = NULL;

}

else

{

pre->next = p->next;

p->next = NULL;

free(p);

p = NULL;

}

 

}

 

return first;

}

/*

Print_linkedlist:打印链表

*/

void Print_linkedlist(struct node*first)

{

printf("==============\n");

struct node*p = first;

while(p)

{

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

p = p->next;

}

printf("\n");

}

 

 

练习:

修改:

在链表first中,找到值为x的数据节点,将其节点的值改为y

如果有多个值为x的数据节点,修改第一个数据节点。若没有

不需要修改。将新链表返回。

 

struct node*Change_node(struct node*first,ElemType x,ElemType y)

{

 

}

 

增加:

在链表first中,找到值为x的节点,在其前面,增加一个节点,新增加的节点

值为y,然后把新链表的首节点的地址返回。假如有多个值为x的节点,则在第一个值

x的节点前添加,如果没有值为x的节点则在最后添加

 

struct node*add_a_node(struct node*first,ElemType x,ElemType y)

{

 

}

 

删除:

在链表first中,找到值为x的节点,将其删除。

然后把新链表的首节点的地址返回。假如有多个值为x的节点,则删除第一个值为x的第一个节点,

如果没有值为x的节点则不删除

struct node*delete_a_node(struct node*first,ElemType x)

{

struct node*p = first;//遍历指针

//step1:查找值为x的节点

while(p)

{

if(p->data == x)

{

break;

}

p = p->next;

}

 

//step2:删除

if(p)

{

if(p == first)

{

first = first->next;

p->next = NULL;

free(p);

p = NULL;

}

 

}

}

 

 

作业:

1.在链表first中,找到值为x的节点,在其后面,增加一个节点,新增加的节点

值为y,然后把新链表的首节点的地址返回。假如有多个值为x的节点,则在第一个值

x的节点前添加,如果没有值为x的节点则在最后添加

 

struct node*add_an_element(struct node*first,ElemType x,ElemType y)

{

 

}

 

 

2.在链表first中,找到所有值为x的节点,将其删除。

然后把新链表的首节点的地址返回。

如果没有值为x的节点则不删除

 

 

3.将一个链表升序 ,附加代码

 

1 5 6 2 3 6

=

1 2 3 5 6 6

/*

将一个链表排序(升序)

*/

struct node*Sort_inc(struct node*first)

{

struct node*pnew = first;//保存新拆下来的节点

struct node*f = NULL;//保存新组合的链表的首节点

while(pnew)

{

//把指定的链表的节点拆下来

first = first->next;

pnew->next = NULL;

 

//重新组合

if(f == NULL)

{

f = pnew;

}

else

{

struct node*p = f;

struct node*pre = NULL;

while(p)

{

if(p->data > pnew->data)

{

break;

}

pre = p;

p = p->next;

}

if(p)//找到了

{

if(p == f)

{

pnew->next = f;

f = pnew;

}

else

{

pnew->next = p;

pre->next = pnew;

}

}

else

{

pre->next = pnew;

}

}

 

pnew = first;

}

 

return f;

}

/*

Create_sort_Linkedlist:创建一条升序链表

*/

struct node*Create_sort_Linkedlist()

{

struct node*first = NULL;

//struct node*last = NULL;

ElemType d;

while(1)

{

//step1:获取一个数据,就创建一个节点

scanf("%d",&d);

if(d == 0)

{

break;

}

struct node*pnew = malloc(sizeof(struct node));

 

//step2:把获取的数据写入到节点中

 pnew->data = d;

 pnew->next = NULL;

 

//step3:把新创建的节点加入到链表中

if(first == NULL)//从无到有

{

first = pnew;

}

else//尾插法

{

struct node*p = first;

struct node*pre = NULL;

while(p)

{

if(p->data > pnew->data)

{

break;

}

pre = p;

p = p->next;

}

if(p)//找到了

{

if(p == first)

{

pnew->next = first;

first = pnew;

}

else

{

pnew->next = p;

pre->next = pnew;

}

}

else

{

pre->next = pnew;

}

}

}

 

return first;

}

4.就地逆置一个单链表(不允许申请新的节点空间)代码

1 5 6 2 3 6

=

6 3 2 6 5 1

/*

Reverse:就地逆置一个单链表(不允许申请新的节点空间)

*/

struct node*Reverse(struct node*first)

{

if(first == NULL || first->next == NULL)

{

return first;

}

struct node*p = NULL;//已经逆置的链表的第一个节点

struct node*pre = first;//每一次往回指的节点

 

first = first->next;

pre->next = NULL;

 

while(first)

{

p = first;

first = first->next;

p->next = pre;

pre = p;

}

 

return p;

}

 

 

 

 

 

需要求一个链表中有多少个节点?

 

=》遍历整个链表

 

 

这个是关于一个链表结构体的内存存储方式。Struct node {int x, struct node*prev, struct node*next;}node;

32位系统中用12个字节存储。前4个存储int型的数值,中间和后面共8个的话存储地址。

 

带头结点的单链表  代码

头结点 用来管理和唯一标识这个链表

#ifndef _LINKEDLIST_H_

#define _LINKEDLIST_H_

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

typedef int ElemType;

struct node

{

ElemType data;

struct node*next;

};

struct Linkedlist

{

struct node*first;//指向链表中第一个节点

struct node*last;//指向链表中最后一个节点

int num;

char name[32];

//....还可以定义其他成员变量,看情况

};

/*

Create_LinkedListWithHead:创建一个带头结点的单向链表

*/

struct Linkedlist*Create_LinkedListWithHead();

/*

Print :打印带头结点的单向链表

*/

void Print(struct Linkedlist*list);

struct Linkedlist*add_a_node(struct Linkedlist*list,ElemType x,ElemType y);

struct Linkedlist*Change_node(struct Linkedlist*list,ElemType x,ElemType y);

struct Linkedlist*delete_a_node(struct Linkedlist*,ElemType );

struct Linkedlist*delete_all_xnode(struct Linkedlist*list,ElemType x);

 

#endif

 

typedef int ElemType;

struct node

{

ElemType data;

struct node*next;

};

struct Linkedlist

{

struct node*first;//指向链表中第一个节点

struct node*last;//指向链表中最后一个节点

int num;

char name[32];

//....还可以定义其他成员变量,看情况

};

 

====

/*

Create_LinkedListWithHead:创建一个带头结点的单向链表

*/

struct Linkedlist*Create_LinkedListWithHead()

{

//step1:创建一个头节点,并赋值

struct Linkedlist*list = malloc(sizeof(struct Linkedlist));

list->first = list->last = NULL;

list->num = 0;

strcpy(list->name,"pxl");

ElemType d;

while(1)

{

//step2:获取一个数据,就创建一个数据节点

scanf("%d",&d);

if(d == 0)

break;

 

struct node*pnew = malloc(sizeof(struct node));

//step3:把获取的数据赋值给数据节点

pnew->data = d;

pnew->next = NULL;

 

//step4:把新的数据节点加入到链表中

if(list->first == NULL)//空链表

{

list->first = pnew;

list->last = pnew;

}

else

{

list->last->next = pnew;

list->last = pnew;

}

 

 

list->num++;

}

 

return list;

}

 

/*

Change_node:在链表list中,找到值为x的数据节点,将其节点的值改为y

如果有多个值为x的数据节点,修改第一个数据节点。若没有

不需要修改。将新链表返回。

*/

struct Linkedlist*Change_node(struct Linkedlist*list,ElemType x,ElemType y)

{

struct node*p = list->first;

while(p)

{

if(p->data == x)

{

p->data = y;

break;

}

p = p->next;

}

 

return list;

}

 

/*

add_a_node:在链表list中,找到值为x的节点,在其前面,增加一个节点,新增加的节点

值为y,然后把新链表的首节点的地址返回。假如有多个值为x的节点,则在第一个值

x的节点前添加,如果没有值为x的节点则在最后添加

*/

struct Linkedlist*add_a_node(struct Linkedlist*list,ElemType x,ElemType y)

{

struct node*p = list->first;//遍历指针

struct node*pre = NULL;//指向p前面的一个节点

 

//step1:创建新的数据节点并赋值

struct node*pnew = malloc(sizeof(*pnew));

pnew->data = y;

pnew->next = NULL;

 

//step2:找到值为x节点

while(p)

{

if(p->data == x)

break;

pre = p;

p = p->next;

}

//step3:插入

if(p)//找到

{

if(p == list->first)

{

pnew->next = list->first;

list->first = pnew;

}

else

{

pnew->next = p;

pre->next = pnew;

}

}

else//未找到

{

if(list->first == NULL)

{

list->first = pnew;

list->last = pnew;

}

else

{

list->last->next = pnew;

list->last = pnew;

}

}

 

list->num++;

return list;

}

 

/*

delete_a_node:在链表list中,找到值为x的节点,将其删除。

然后把新链表的首节点的地址返回。假如有多个值为x的节点,则删除第一个值为x的第一个节点,

如果没有值为x的节点则不删除

*/

struct Linkedlist*delete_a_node(struct Linkedlist*list,ElemType x)

{

struct node*p = list->first;//遍历指针

struct node*pre = NULL;//指向p前面的一个节点

//step1:找到值为x的数据节点

while(p)

{

if(p->data == x)

break;

pre = p;

p = p->next;

}

 

//step2:删除

if(p)//找到了

{

if(p == list->first)//首节点

{

list->first = p->next;

p->next = NULL;

//free(p);

//p = NULL;

}

else if(p == list->last)

{

list->last = pre;

list->last->next = NULL;

//free(p);

//p = NULL;

}

else

{

pre->next = p->next;

p->next = NULL;

//free(p);

//p = NULL;

}

free(p);

p = NULL;

 

list->num--;

 

}

 

return list;

}

 

/*

delete_all_xnode

在链表first中,找到值为x的节点,将其删除。

然后把新链表的首节点的地址返回。假如有多个值为x的节点,则全部删除,

如果没有值为x的节点则不删除

 

*/

struct Linkedlist*delete_all_xnode(struct Linkedlist*list,ElemType x)

{

struct node*p = list->first;

struct node*pre = NULL;

 

while(p)

{

if(p->data == x)

{

if(p == list->first)//首节点

{

list->first = p->next;

p->next = NULL;

free(p);

p = list->first;

}

else if(p == list->last)

{

list->last = pre;

list->last->next = NULL;

free(p);

p = NULL;

}

else

{

pre->next = p->next;

p->next = NULL;

free(p);

p = pre->next;

}

 

list->num--;

}

else

{

pre = p;

p = p->next;

}

 

 

}

return list;

}

/*

Print :打印带头结点的单向链表

*/

void Print(struct Linkedlist*list)

{

printf("====================\n");

struct node*p = list->first;

while(p)

{

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

p = p->next;

}

printf("\n");

}

练习:

修改:在链表list中,找到值为x的数据节点,将其节点的值改为y

如果有多个值为x的数据节点,修改第一个数据节点。若没有

不需要修改。将新链表返回。

 

struct Linkedlist*Change_node(struct Linkedlist*list,ElemType x,ElemType y)

{

 

}

 

增加:

在链表list中,找到值为x的节点,在其前面,增加一个节点,新增加的节点

值为y,然后把新链表的首节点的地址返回。假如有多个值为x的节点,则在第一个值

x的节点前添加,如果没有值为x的节点则在最后添加

 

struct Linkedlist*add_a_node(struct Linkedlist*,ElemType x,ElemType y)

{

 

}

 

删除单个:

在链表first中,找到值为x的节点,将其删除。

然后把新链表的首节点的地址返回。假如有多个值为x的节点,则删除第一个值为x的第一个节点,

如果没有值为x的节点则不删除

struct Linkedlist*delete_a_node(struct Linkedlist*,ElemType x)

{

 

}

删除全部为x的节点:

在链表first中,找到值为x的节点,将其删除。

然后把新链表的首节点的地址返回。假如有多个值为x的节点,则全部删除,

如果没有值为x的节点则不删除

struct Linkedlist*delete_a_node(struct Linkedlist*,ElemType x)

{

 

}

 

作业:

1.归并两个有序链表(升序)  =》不带头节点的单向链表代码

合并两个升序链表变成一个升序链表

 

1 2 3 4 5

2 4 6 8

/*

merge:归并两个有序链表(升序)  =》不带头节点的单向链表

合并两个升序链表变成一个升序链表

算法:

step1:取原先链表中的最小节点,摘下来

step2:重新组合(尾插法)

*/

struct node*merge(struct node*pa,struct node*pb)

{

struct node*pnew = NULL;

struct node*first = NULL;//指向的是新组合的链表的首节点

struct node*last = NULL;//指向的是新组合的链表的尾节点

 

while(pa&&pb)

{

//step1:取原先链表中的最小节点,摘下来

if(pa->data < pb->data)

{

pnew = pa;

pa = pa->next;

pnew->next = NULL;

}

else

{

pnew = pb;

pb = pb->next;

pnew->next = NULL;

}

//step2:重新组合(尾插法)

if(first == NULL)

{

first = pnew;

last = pnew;

}

else

{

last->next = pnew;

last = pnew;

}

 

}

 

if(last == NULL)

{

first = pa ? pa : pb;

}

else

{

last->next = pa ? pa : pb;

}

 

 

return first;

}

2.返回一个带头节点的单向链表中的倒数第K个节点的指针代码

// 作业题2:2.返回一个带头节点的单向链表中的倒数第K个节点的指针

//是不是意味着是顺数第list->num-k+1呢?3

struct node * the_backnum_k(struct Linkedlist*list, int k)

{

struct node *p =NULL;

int count = 0;

p = list->first;

while(p)

{

count++;

if(count == list->num - k + 1)

{

break;

}

p = p->next;

}

return p;

}

3.链表A,B,判断A 是否为 B 的子序列,是返回1,不是返回0代码

 

子序列:连续的一部分

 

A :3 5 6

 

B1 2 3 5 6 8 9

/*

链表A,B,判断A 是否为 B 的子序列,是返回1,不是返回0

*/

int Sonlist(struct Linklist*A,struct Linklist*B)

{

struct node*pa = A->first;

struct node*pb = B->first;

struct node*pbs = B->first;//指向下次B开始的节点

while(pbs)

{

pb = pbs;

pa = A->first;

while(pa&&pb)

{

 

if(pa->data != pb->data)

{

break;

}

else

{

pa = pa->next;

pb = pb->next;

if(pb == NULL)

return 0;//b的长度小于a

}

}

if(pa == NULL)

return 1;

pbs = pbs->next;

}

 

}

4、带头结点的双向链表插入排序,代码

/*

带头节点的双向链表的插入排序(创建一条升序带头节点的双向链表)

*/

struct Linkedlist*Create_Sort_BothWayLinkedListWithHead()

{

//step1:创建一个头节点,并赋值

struct Linkedlist*list = malloc(sizeof(*list));

list->first = list->last = NULL;

list->num = 0;

strcpy(list->name,"pxl");

 

ElemType d;

while(1)

{

//step2:获取一个数据,就创建一个数据节点

scanf("%d",&d);

if(d == 0)

break;

struct node*pnew = malloc(sizeof(*pnew));

 

//step3:把获取的数据赋值给数据节点

pnew->data = d;

pnew->next = pnew->prev = NULL;

 

//step4:把新的数据节点加入到链表中

if(list->first == NULL)//空链表

{

list->first = pnew;

list->last = pnew;

}

else//尾插法

{

struct node*p = list->first;

while(p)

{

if(p->data > pnew->data)

break;

p = p->next;

}

 

if(p)

{

if(p == list->first)

{

pnew->next = list->first;

list->first->prev = pnew;

list->first = pnew;

}

else

{

pnew->next = p;

pnew->prev = p->prev;

pnew->prev->next = pnew;

pnew->next->prev = pnew;

}

}

else

{

list->last->next = pnew;

pnew->prev = list->last;

list->last = pnew;

}

}

 

 

list->num++;

}

 

return list;

}

4、A,B为单链表,且A,B为升序,求A,B的交集(AB都有元素),重新组成为一个链表C,代码

原来的链表不动(AB),C也要升序

 

A:1 2 3 3 3

B:1 2 3 3 6 6 7

 

C:1 2 3 6                                                                              

 

struct node* XXXXX(struct node*a,struct node*b)

{

struct node*first = NULL;//C链表的首节点

struct node*last = NULL;//C链表的尾节点

 

struct node*pa = a;//C链表的首节点

struct node*pb = b;//C链表的尾节点

 

while(pa&&pb)

{

if(pa->data == pb->data)

{

if(last == NULL || pa->data != last->data)

{

struct node*pnew = malloc(sizeof(*pnew));

pnew->data = pa->data;

pnew->next = NULL;

if(first == NULL)

{

first = pnew;

last = pnew;

}

else

{

last->next = pnew;

last = pnew;

}

}

pa = pa->next;

pb = pb->next;

}

else if(pa->data > pb->data)

{

pb = pb->next;

}

else

{

pa = pa->next;

}

}

 

return first;

}

 

带头结点的双向链表:代码:

BothWayLinkedlistWithHead.h代码内容

#ifndef _LINKEDLIST_H_

#define _LINKEDLIST_H_

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

typedef int ElemType;

struct node

{

ElemType data;

struct node*next;

struct node*prev;

};

struct Linkedlist

{

struct node*first;//指向链表中第一个节点

struct node*last;//指向链表中最后一个节点

int num;

char name[32];

//....还可以定义其他成员变量,看情况

};

/*

Create_LinkedListWithHead:创建一个带头结点的双向链表

*/

struct Linkedlist*Create_BothWayLinkedListWithHead();

/*

Print :打印带头结点的双向链表

*/

void Print(struct Linkedlist*list);

struct Linkedlist*add_a_node(struct Linkedlist*list,ElemType x,ElemType y);

struct Linkedlist*Change_node(struct Linkedlist*list,ElemType x,ElemType y);

struct Linkedlist*delete_a_node(struct Linkedlist*,ElemType );

struct Linkedlist*delete_all_xnode(struct Linkedlist*list,ElemType x);

 

#endif

BothWayLinkedlistWithHead.c的代码内容是:

#include "BothWayLinkedlistWithHead.h"

/*

Create_LinkedListWithHead:创建一个带头结点的双向链表

*/

struct Linkedlist*Create_BothWayLinkedListWithHead()

{

//step1:创建一个头节点,并赋值

struct Linkedlist*list = malloc(sizeof(*list));

list->first = list->last = NULL;

list->num = 0;

strcpy(list->name,"pxl");

 

ElemType d;

while(1)

{

//step2:获取一个数据,就创建一个数据节点

scanf("%d",&d);

if(d == 0)

break;

struct node*pnew = malloc(sizeof(*pnew));

 

//step3:把获取的数据赋值给数据节点

pnew->data = d;

pnew->next = pnew->prev = NULL;

 

//step4:把新的数据节点加入到链表中

if(list->first == NULL)//空链表

{

list->first = pnew;

list->last = pnew;

}

else//尾插法

{

pnew->prev = list->last;

list->last->next = pnew;

list->last = pnew;

}

 

 

list->num++;

}

 

return list;

}

 

/*

Change_node:在链表list中,找到值为x的数据节点,将其节点的值改为y

如果有多个值为x的数据节点,修改第一个数据节点。若没有

不需要修改。将新链表返回。

*/

struct Linkedlist*Change_node(struct Linkedlist*list,ElemType x,ElemType y)

{

struct node*p = list->first;

while(p)

{

if(p->data == x)

{

p->data = y;

break;

}

p = p->next;

}

return list;

}

 

/*

add_a_node:在链表list中,找到值为x的节点,在其前面,增加一个节点,新增加的节点

值为y,然后把新链表的首节点的地址返回。假如有多个值为x的节点,则在第一个值

x的节点前添加,如果没有值为x的节点则在最后添加

*/

struct Linkedlist*add_a_node(struct Linkedlist*list,ElemType x,ElemType y)

{

struct node*p = list->first;//遍历指针

 

//step1:创建新的数据节点并赋值

struct node*pnew = malloc(sizeof(*pnew));

pnew->data = y;

pnew->next = pnew->prev = NULL;

 

//step2:找到值为x节点.

while(p)

{

if(p->data == x)

break;

 

p = p->next;

}

//step3:插入

if(p)

{

if(p == list->first)//p在首节点处

{

pnew->next = list->first;

p->prev = pnew;

list->first = pnew;

}

else

{

pnew->next = p;

pnew->prev = p->prev;

p->prev->next = pnew;

p->prev = pnew;

}

}

else

{

if(list->first == NULL)

{

list->first = pnew;

list->last = pnew;

}

else

{

list->last->next = pnew;

pnew->prev = list->last;

list->last = pnew;

}

}

list->num++;

return list;

}

 

/*

delete_a_node:在链表list中,找到值为x的节点,将其删除。

然后把新链表的首节点的地址返回。假如有多个值为x的节点,则删除第一个值为x的第一个节点,

如果没有值为x的节点则不删除

*/

struct Linkedlist*delete_a_node(struct Linkedlist*list,ElemType x)

{

struct node*p = list->first;

 

//找到值为x的数据节点

while(p)

{

if(p->data == x)

break;

p = p->next;

}

if(p)

{

if(p == list->first)

{

if(list->num == 1)

{

list->first = NULL;

list->last = NULL;

}

else

{

list->first = list->first->next;

p->next->prev = NULL;

p->next = NULL;

}

//free(p);

//p = NULL;

}

else if(p == list->last)

{

p->prev->next = NULL;

list->last = p->prev;

p->prev = NULL;

//free(p);

//p = NULL;

}

else

{

p->next->prev = p->prev;

p->prev->next = p->next;

p->next = NULL;

p->prev = NULL;

//free(p);

//p = NULL;

}

free(p);

p = NULL;

list->num--;

 

}

 

return list;

}

 

/*

delete_all_xnode

在链表first中,找到值为x的节点,将其删除。

然后把新链表的首节点的地址返回。假如有多个值为x的节点,则全部删除,

如果没有值为x的节点则不删除

 

*/

struct Linkedlist*delete_all_xnode(struct Linkedlist*list,ElemType x)

{

struct node*p = list->first;

struct node*pn = NULL;

//找到值为x的数据节点

while(p)

{

if(p->data == x)

{

if(p == list->first)

{

if(list->num == 1)

{

list->first = NULL;

list->last = NULL;

free(p);

p = NULL;

}

else

{

list->first = list->first->next;

p->next->prev = NULL;

p->next = NULL;

free(p);

p = list->first;

}

 

}

else if(p == list->last)

{

p->prev->next = NULL;

list->last = p->prev;

p->prev = NULL;

free(p);

p = NULL;

}

else

{

pn = p->next;

p->next->prev = p->prev;

p->prev->next = p->next;

p->next = NULL;

p->prev = NULL;

free(p);

p = pn;

}

 

list->num--;

}

else

{

p = p->next;

}

 

}

 

return list;

}

/*

带头节点的双向链表的插入排序(创建一条升序带头节点的双向链表)

*/

struct Linkedlist*Create_Sort_BothWayLinkedListWithHead()

{

//step1:创建一个头节点,并赋值

struct Linkedlist*list = malloc(sizeof(*list));

list->first = list->last = NULL;

list->num = 0;

strcpy(list->name,"pxl");

 

ElemType d;

while(1)

{

//step2:获取一个数据,就创建一个数据节点

scanf("%d",&d);

if(d == 0)

break;

struct node*pnew = malloc(sizeof(*pnew));

 

//step3:把获取的数据赋值给数据节点

pnew->data = d;

pnew->next = pnew->prev = NULL;

 

//step4:把新的数据节点加入到链表中

if(list->first == NULL)//空链表

{

list->first = pnew;

list->last = pnew;

}

else//尾插法

{

struct node*p = list->first;

while(p)

{

if(p->data > pnew->data)

break;

p = p->next;

}

 

if(p)

{

if(p == list->first)

{

pnew->next = list->first;

list->first->prev = pnew;

list->first = pnew;

}

else

{

pnew->next = p;

pnew->prev = p->prev;

pnew->prev->next = pnew;

pnew->next->prev = pnew;

}

}

else

{

list->last->next = pnew;

pnew->prev = list->last;

list->last = pnew;

}

}

 

 

list->num++;

}

 

return list;

}

 

/*

Print :打印带头结点的单向链表

*/

void Print(struct Linkedlist*list)

{

printf("next====================\n");

struct node*p = list->first;

while(p)

{

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

p = p->next;

}

printf("\n");

/*

printf("prev====================\n");

p = list->last;

while(p)

{

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

p = p->prev;

}

 

printf("\n");

*/

}

 

main.c

#include <stdio.h>

#include "BothWayLinkedlistWithHead.h"

 

int main()

{

struct Linkedlist*l = Create_Sort_BothWayLinkedListWithHead();

 

printf("num = %d\n",l->num);

 

//l = add_a_node(l,2,3);

//l = delete_a_node(l,2);

 

//l = delete_all_xnode(l,2);

//printf("num = %d\n",l->num);

 

Print(l);

 

//printf("num = %d\n",l->num);

 

}

END

Copyright © 2024 不叫柒桓叶
Powered by .NET 9.0 on Kubernetes