当前位置:   article > 正文

双向链表是一个环吗 c语言,创建三种基本链表你都会了吗?

双向链表是个圆吗

今天我要带领大家走进创建链表的世界,大家准备好了吗?

go!!!

------------

No.1 单链表

- 特点1——链表的链接方向是单向的;

- 特点2——对链表的访问要通过顺序读取从头部开始。

No.2 双链表

- 结点除含有数据域外,还有两个链域,一个存储直接后继结点地址,一般称之为右链域;一个存储直接前驱结点地址,一般称之为左链域。

No.3 循环链表

- 循环链表是与单链表一样,是一种链式的存储结构,所不同的是,循环链表的最后一个结点的指针是指向该循环链表的第一个结点或者表头结点,从而构成一个环形的链。

#### 单链表 Battle 双链表

1、指向不同:

单向链表只有一个指向下一结点的指针,双向链表除了有一个指向下一结点的指针外,还有一个指向前一结点的指针。

2、功能不同:

单向链表只能next ,双向链表可以return。

3、单双向不同:

单链表只能单向读取,双向链表可以通过prev()快速找到前一结点。

**单向链表优缺点:**

1、优点:单向链表增加删除节点简单。遍历时候不会死循环;

2、缺点:只能从头到尾遍历。只能找到后继,无法找到前驱,也就是只能前进。

**双向链表优缺点**:

1、优点:可以找到前驱和后继,可进可退;

2、缺点:增加删除节点复杂,多需要分配一个指针存储空间。

![](/image_editor_upload/20190622092016_69900.png)

**适用情况**

1.单向链表适用于节点的增加删除。

2.双向链表适用于需要双向查找节点值的情况。

#### 单链表 Battle 循环链表

循环链表的运算与单链表的运算基本一致。所不同的有以下几点:

1、在建立一个循环链表时,必须使其最后一个结点的指针指向表头结点,而不是象单链表那样置为NULL。此种情况还使用于在最后一个结点后插入一个新的结点。

2、在判断是否到表尾时,是判断该结点链域的值是否是表头结点,当链域值等于表头指针时,说明已到表尾。而非象单链表那样判断链域值是否为NULL

### 码上代码

一、创建单链表

```c

#include#includestruct LNode

{

int data;

struct LNode *next;

};

struct LNode *create(int n)

{

int i,a;

struct LNode *head,*p1,*p2;

head = NULL;

printf("输入整数:\n");

for(i=n;i>0;--i)

{

p1 = (struct LNode*)malloc(sizeof(struct LNode));

scanf("%d",&a);

p1->data = a;

if(head==NULL) //指定头节点

{

head = p1;

p2 = p1;

}

else

{

p2->next = p1; //指定后继指针

p2 = p1;

}

}

p2->next = NULL;

return head;

}

int main()

{

int n;

struct LNode *q;

printf("你想创建的节点数:\n");

scanf("%d",&n);

q = create(n);

printf("结果是:\n");

while(q)

{

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

q = q->next;

};

return 0;

}

```

结果运行图:

![](/image_editor_upload/20190622093024_21018.png)

二、创建双向链表

```c

#include#include#include//双链表的结构定义

typedef struct node

{

char name[20];

struct node *prior,*next;

}stud;

stud *creat(int n)

{

stud *p,*h,*s;

int i;

h = (stud*)malloc(sizeof(stud));

h->name[0] = '\0';

h->prior = NULL;

h->next = NULL;

p = h;

for(i=0;inext = s; //指定后继节点

printf("\n输入第%d个学生的姓名:",i+1);

scanf("%s",s->name);

s->prior = p; //指定前驱节点

s->next = NULL;

p = s;

}

p->next = NULL;

return h;

}

//定义search函数,实现要删除的节点,如果找到则返回该节点的地址

stud *search(stud *h,char *x)

{

stud *p; //指向结构体类型的指针

char *y;

p = h->next;

while(p)

{

y = p->name;

if(strcmp(y,x)==0) //如果要删除节点,则返回地址

return p;

else

p = p->next;

}

printf("没有找到数据!\n");

}

//定义函数del,实现删除链表中的指定节点

void del(stud *p)

{

p->next->prior = p->prior; //*p的下一个节点的前驱指针指向p的前驱节点

p->prior->next = p->next; //*p的前驱节点的后继指针指向p的后继节点

free(p);

}

int main()

{

int num;

char sname[20];

stud *head, *sp;

puts("请输入链表的大小:");

scanf("%d",&num);

head = creat(num);

sp = head->next;

printf("\n链表是:\n");

while(sp)

{

printf("%s ",&*(sp->name));

sp = sp->next;

}

printf("\n请输入你想要删除的姓名: \n");

scanf("%s",sname);

sp = search(head,sname);

del(sp);

sp = head->next;

printf("\n现在这个双向链表是:\n");

while(sp)

{

printf("%s ",&*(sp->name));

sp = sp->next;

}

return 0;

}

```

运行结果:

![](/image_editor_upload/20190622093132_36114.png)

三、创建循环链表

```c

#include#includetypedef struct student

{

int num;

struct student *next;

}LNode, *LinkList;

LinkList create(void)

{

LinkList head;

LNode *p1,*p2;

char a;

head = NULL;

a = getchar();

while(a!='\n')

{

p1 = (LNode*)malloc(sizeof(LNode));

p1->num = a;

if(head==NULL)

head = p1;

else

p2->next = p1;

p2 = p1;

a = getchar();

}

p2->next = head;

return head;

}

int main()

{

LinkList L1,head;

printf("请输入循环链表: \n");

L1 = create();

head = L1;

printf("链表为:\n");

printf("%c ",L1->num);

L1 = L1->next;

while(L1!=head) //指向下一个节点

{

printf("%c ",L1->num);

L1 = L1->next;

}

return 0;

}

```

运行结果:

![](/image_editor_upload/20190622093246_35517.png)

喜欢的小可爱不要忘了点赞哦!!!

0.0分

10 人评分

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/681897
推荐阅读
相关标签
  

闽ICP备14008679号