1.链表

  链表是线性表的一种,由一系列节点(结点)组成,每个节点包含一个数据域和一个指向下一个节点的指针域。链表结构可以克服数组需要预先知道数据大小的缺点,而且插入和删除元素很方便,但是失去数组随机读取的优点。链表有很多种不同类型:单向链表,双向链表和循环链表。

在链表中第一个节点叫头节点(如果有头节点)头节点不存放有效信息,是为了方便链表的删除和插入操作,第一个有效节点叫首节点,最后一个节点叫尾节点。

2.单链表的操作

  链表的操作一般有创建链表,插入节点,删除节点,遍历链表。插入节点的方法有头插法和尾插法,头插法是在头部插入,尾插法是在尾部插入。

  下面以一个带头节点,采用尾插法的链表说明链表的各种操作。

  1 #include<stdio.h>
2 #include<stdlib.h>
3 //单链表
4
5
6 //节点结构体
7 typedef struct node
8 {
9 int value;//数据域
10 struct node*next;//指针域
11 }Node;
12
13 Node*createList();//创建链表并且返回头节点指针
14 void deleteNode(Node*head);//删除节点
15 void insertNode(Node*head);//插入节点
16 void travelList(Node*head);//遍历链表
17
18 int main()
19 {
20 Node*head=createList();
21 travelList(head);
22 insertNode(head);
23 travelList(head);
24 deleteNode(head);
25 travelList(head);
26 return 0;
27 }
28 //创建链表,返回头节点指针
29 Node*createList()
30 {
31 //采用尾插法
32 Node*head;//头节点
33 Node*tail;//尾节点
34 Node*temp=NULL;
35 int i,value,size;
36 head=(Node*)malloc(sizeof(Node));//头节点
37 head->value=0;
38 head->next=NULL;
39 tail=head;
40 printf("输入节点个数: ");
41 scanf("%d",&size);
42 printf("输入各个节点的值: ");
43
44 for(i=0;i<size;i++)
45 {
46 scanf("%d",&value);
47 temp=(Node*)malloc(sizeof(Node));
48 temp->value=value;
49 tail->next=temp;//让尾节点的指针域指向新创建的节点
50 tail=temp;//尾节点改为新创建的节点
51 tail->next=NULL;//让尾节点的指针域为空
52 }
53 return head;
54 }
55 //遍历链表
56 void travelList(Node*head)
57 {
58 while(head->next!=NULL)
59 {
60 printf("%d\n",head->next->value);
61 head=head->next;
62 }
63 }
64 //插入节点
65 void insertNode(Node*head)
66 {
67 int value;
68 int position;
69 int pos=0;
70 Node*pre=NULL;//用来保存要插入节点的前一个节点
71 Node*newNode;
72 printf("输入要插入节点的值: ");
73 scanf("%d",&value);
74 printf("要插入的位置: ");
75 scanf("%d",&position);
76 while(head!=NULL)
77 {
78 pos++;
79 pre=head;
80 head=head->next;
81 if(pos==position)
82 {
83 newNode=(Node*)malloc(sizeof(Node));
84 newNode->value=value;
85 newNode->next=pre->next;
86 pre->next=newNode;
87 }
88 }
89 }
90 //删除节点
91 void deleteNode(Node*head)
92 {
93 int value;
94 Node*pre=head;
95 Node*current=head->next;
96 printf("输入要删除节点的值: ");
97 scanf("%d",&value);
98 while(current!=NULL)
99 {
100 if(current->value==value)
101 {
102 pre->next=current->next;
103 free(current);//释放空间
104 break;
105 }
106 pre=current;
107 current=current->next;
108 }
109 }

3.循环链表

  循环链表就是让尾节点的指针域不再是NULL,而是指向头节点从而形成一个环。循环链表与单链表的操作没有多少差别,只是判断链表是否空应该是

  tail->next==head。

4.双向链表

  双向链表的每一个节点都有两个指针域,一个前驱指针,指向前一个节点,头节点的前驱指针为NULL,一个后继指针,指向后一个节点,尾节点的后继指针为NULL。双向链表可以从任一个节点开始访问到前后节点,不像单链表只能向前。代码如下。

  1 #include<stdio.h>
2 #include<stdlib.h>
3 //双向链表
4 typedef struct node
5 {
6 int value;//数据域
7 struct node* lNext;//前驱指针
8 struct node* rNext;//后继指针
9 }Node;
10
11 Node*createList();//创建链表并且返回头节点指针
12 void deleteNode(Node*head);//删除节点
13 void insertNode(Node*head);//插入节点
14 void travelList(Node*head);//遍历链表
15
16 int main()
17 {
18
19 Node*head=createList();
20 travelList(head);
21 insertNode(head);
22 travelList(head);
23 deleteNode(head);
24 travelList(head);
25 return 0;
26 }
27
28 Node*createList()
29 {
30 Node*head,*tail,*temp;
31 int num,value,i;
32 head=(Node*)malloc(sizeof(Node));//头节点
33 head->value=0;
34 head->lNext=NULL;
35 head->rNext=NULL;
36 tail=head;
37 printf("输入节点个数: ");
38 scanf("%d",&num);
39 printf("输入各个节点的值: ");
40 for(i=0;i<num;i++)
41 {
42 scanf("%d",&value);
43 temp=(Node*)malloc(sizeof(Node));
44 temp->value=value;
45 temp->lNext=tail;
46 tail->rNext=temp;
47 tail=temp;
48 tail->rNext=NULL;
49 }
50 return head;
51 }
52
53
54 void deleteNode(Node*head)//删除节点
55 {
56
57 int value;
58 Node*pre;
59 Node*current=head->rNext;
60 printf("输入要删除节点的值: ");
61 scanf("%d",&value);
62 pre=head;
63 while(current!=NULL)
64 {
65 if(current->value==value)
66 {
67 pre->rNext=current->rNext;//上一个节点指向下一个节点
68 current->rNext->lNext=pre;//下一个节点的前驱指针指向上一个节点
69 free(current);//删除该节点
70 }
71 pre=current;
72 current=current->rNext;
73 }
74 }
75
76 void insertNode(Node*head)//插入节点
77 {
78 Node*pre,*temp;
79 int value,pos;
80 int num=0;
81 printf("输入要插入的值: ");
82 scanf("%d",&value);
83 printf("输入要插入的位置: ");
84 scanf("%d",&pos);
85 while(head!=NULL)
86 {
87 num++;
88 pre=head;//保存上一个节点
89 head=head->rNext;//当前节点
90 if(pos==num)
91 {
92 temp=(Node*)malloc(sizeof(Node));
93 temp->value=value;
94 temp->lNext=pre;
95 temp->rNext=head;
96 head->lNext=temp;
97 pre->rNext=temp;
98 }
99 }
100 }
101
102 void travelList(Node*head)//遍历链表
103 {
104 while(head->rNext!=NULL)
105 {
106 printf("%d\n",head->rNext->value);
107 head=head->rNext;
108 }
109 }

  其实只要弄懂单链表,其他也很简单的,无论链表多复杂,本质还是操作指针的指向,想想就会明白了。

  如果链表不会,后面的各种各样的树结构,就更不用学了。

数据结构之链表篇(单链表,循环链表,双向链表)C语言版的更多相关文章

  1. 数据结构之 线性表---单链表的操作B(先逆序+再删除重复元素)

    数据结构上机测试2-2:单链表操作B Time Limit: 1000MS Memory limit: 65536K 题目描述 按照数据输入的相反顺序(逆位序)建立一个单链表,并将单链表中重复的元素删 ...

  2. 数据结构之 线性表---单链表操作A (删除链表中的指定元素)

    数据结构上机测试2-1:单链表操作A Time Limit: 1000MS Memory limit: 4096K 题目描述 输入n个整数,先按照数据输入的顺序建立一个带头结点的单链表,再输入一个数据 ...

  3. 数据结构5: 链表(单链表)的基本操作及C语言实现

    逻辑结构上一个挨一个的数据,在实际存储时,并没有像顺序表那样也相互紧挨着.恰恰相反,数据随机分布在内存中的各个位置,这种存储结构称为线性表的链式存储. 由于分散存储,为了能够体现出数据元素之间的逻辑关 ...

  4. [C++]线性链表之单链表

    [文档整理系列] 线性链表之单链表 /* 问题描述:线性表____链表_____单链表 @date 2017-3-7 */ #include<iostream> using namespa ...

  5. js数据结构之链表(单链表、双向链表、循环链表)

    首先,链表有以下特点: 1. 存储空间不固定,可灵活扩充 2.方便多次的插入和删除,效率较高 单链表 单链表是最常用的链表,其对数据的操作均为单项的,向后查找的. /* 链表(基于对象) 此处为单链表 ...

  6. Java数据结构-线性表之单链表LinkedList

    线性表的链式存储结构,也称之为链式表,链表:链表的存储单元能够连续也能够不连续. 链表中的节点包括数据域和指针域.数据域为存储数据元素信息的域,指针域为存储直接后继位置(一般称为指针)的域. 注意一个 ...

  7. 《数据结构》2.3单链表(single linked list)

    //单链表节点的定义 typedef struct node { datatype data; struct node *next; }LNode,*LinkList; //LNode是节点类型,Li ...

  8. C:数据结构与算法之单链表

    单链表相对于顺序表比较难理解,但是比较实用,单链表的插入,删除不需要移动数据元素,只需要一个指针来寻找所需要的元素,还有一个大优点就是不浪费空间,当你想要增加一个结点可以申请(malloc())一个结 ...

  9. python数据结构与算法之单链表

    表的抽象数据类型 ADT list:                      #一个表的抽象数据类型 List(self)               #表的构造操作,创建一个空表 is_empty ...

  10. 【c++版数据结构】之循环单链表的实现(带头结点以及尾节点)

    所实现的循环单链表的结构例如以下图所看到的: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill ...

随机推荐

  1. 从源码分析 SpringBoot 的 LoggingSystem → 它是如何绑定日志组件的

    开心一刻 今天心情不好,想约哥们喝点 我:心情不好,给你女朋友说一声,来我家,过来喝点 哥们:行!我给她说一声 我:你想吃啥?我点外卖 哥们:你俩定吧,我已经让她过去了 我:???我踏马让你过来!和她 ...

  2. Vue elementui 进度条随机颜色

    项目要求显示进度条,而且进度条的颜色不能重复,所以就有了随机进度条的想法. 实现的最终效果: <el-table-column header-align="center" a ...

  3. Linux 挂载设备

    手动挂载 挂载: # 创建挂载目录 sudo mkdir -p /path/to/mount # 挂载 sudo mount /dev/sdX1 /path/to/mount # 确认挂载 df -h ...

  4. android 反编译APK取源代码。

    坑,自己写的Android APK 程序,发现线上版本是 1.9.4 ,本地的代码版本却是 1.9.1.不知道到底怎么回事,svn里面也没有日志记录.....只能从线上apk反编译来看看了,幸好这个升 ...

  5. 总结篇3:redis 典型缓存架构设计问题及性能优化

    聊聊对于缓存预热.缓存穿透.缓存雪崩.缓存击穿.缓存更新.缓存降级的定义理解 缓存穿透 定义 当查询Redis中没有的数据时,该查询会下沉到数据库层,同时数据库层也没有该数据,当这种情况大量出现或被恶 ...

  6. Azure – 对比 AWS Research Report

    前言 最近有机会接触了一下 AWS, 在对比完之后决定继续用 Azure, 这里小小记入一下. VM & SQL Server Azure 和 AWS 都可以选择 2 in 1, 或者 Web ...

  7. Java SE 23 新增特性

    Java SE 23 新增特性 作者:Grey 原文地址: 博客园:Java SE 23 新增特性 CSDN:Java SE 23 新增特性 源码 源仓库: Github:java_new_featu ...

  8. SpringMVC——SSM整合-异常处理器

    异常处理器 出现异常的常见位置与常见诱因: 框架内部抛出的异常:因使用不合规导致 数据层抛出异常:因外部服务器故障导致(例如:服务器访问超时) 业务层抛出的异常:因业务逻辑书写错误导致(例如:遍历业务 ...

  9. 反问面试官3个ThreadLocal的问题

    ThreadLocal,一个Java人面试绕不开的话题,我也很奇怪为什么那些面试官很喜欢问这个,也不知道他们自己有没有搞清楚. 接下来,我想先说说ThreadLocal的用法和使用场景,然后反问面试官 ...

  10. 伯克利函数调用排行榜(BFCL)

    自 2022 年底以来,大语言模型(LLMs)凭借其执行通用任务的强大能力,成为众人关注的焦点.不仅限于聊天应用,将这些模型应用于开发各类 AI 应用和软件(如 Langchain, Llama In ...