首页 > 编程语言 >「数据结构与算法」链表 —— 看这一篇就够了(超详细)

「数据结构与算法」链表 —— 看这一篇就够了(超详细)

时间:2022-08-23 21:58:08浏览次数:68  
标签:node DoubleLinkedListNode point int 就够 next 链表 数据结构

 一、链表简介

  链表是一种物理存储单元上非连续、非顺序的存储结构,数据结构的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比数组快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而数组只需要O(1)

  使用链表结构可以克服数组需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。

二、链表创建
  链表的的每一个结点都有存储数据元素的数据域与存储下一个结点地址的指针域,所以我们在创建新链表时需要设置一个结点结构体(如下代码块SingleLinkedListNode).且还要拥有一个head指针与tail指针

1 SLL为单向链表,DLL为双向链表,()为value,-->为指针(单向链表),````与____为指针(双向链表)
2 ======================================================================
3 SLL[0](1)----->SLL[1](2)----->SLL[2](3)----->SLL[3](4)
4 Head                          Tail
5 这里我们创建了一个拥有四个元素的SLL
6 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 DLL[0](1)`_`_`_`_`DLL[1](2)`_`_`_`_`DLL[2](3)`_`_`_`_`DLL[3](4)
8 Head                                Tail
9 这里我们创建了一个拥有四个元素的DLL

  单向链表:

1 struct SingleLinkedListNode{
2 int value;
3 struct SingleLinkedListNode *next;
4 }*Shead=NULL,*Stail=NULL;

  如果是双向链表的话则需要有prev指针:

1 struct DoubleLinkedListNode{
2 int value;
3 struct DoubleLinkedListNode *next;
4 struct DoubleLinkedListNode *prev;
5 }*Dhead=NULL,*Dtail=NULL;

  有了结点结构体,我们就可以进行单双链表创建了:

 1 void CreateNewSingleLinkedList(int len){
 2     for (int i=0;i<len;i++){
 3         int inputvalue;
 4         cin >> inputvalue;
 5         SingleLinkedListNode *node = new SingleLinkedListNode;
 6         node->value = inputvalue;
 7         node->next = NULL;
 8         if (!Shead){Shead=node;Stail=node;}
 9         else{Stail->next=node;Stail=node;}
10     }
11 }
12 
13 void CreateNewDoubleLinkedList(int len){
14     for (int i=0;i<len;i++){
15         int inputvalue;
16         cin >> inputvalue;
17         DoubleLinkedListNode *node = new DoubleLinkedListNode;
18         node->value = inputvalue;
19         node->next = NULL;
20         if (!Dhead){Dhead=node;Dtail=node;}
21         else{Dtail->next=node;node->prev=Dtail;Dtail=node;}
22     }
23 }

  先看单链表,我们将CreateNewSingleLinkedList的参数len作为单向链表的长度.接着用for循环依次输入每项数据元素的值,再创建一个新的节点(关键字new),并把它的value设成刚刚输入的值,再将它的next项设为NULL.接下来判读如果!Shead(即单链表中没有元素),将Shead设为新节点,如果已经有其他元素,再将现在的Stail的next项设为新节点,最后让Stail变成新节点.

  双链表也一样,只不过在上述代码第21行(倒数第3行)多了一个新节点的prev项设为Dtail的操作

三、链表输出
  链表的输出从头指针head开始,依次打印数据元素的value,接着再将指针指向下一个元素(单双链表都适用):

 1 void OutputSingleLinkedList(){
 2     SingleLinkedListNode *point = Shead;
 3     while (point) {
 4         cout << point->value << " ";
 5         point = point->next;
 6     }
 7     cout << endl;
 8 }
 9 void OutputDoubleLinkedList(){
10     DoubleLinkedListNode *point = Dhead;
11     while (point) {
12         cout << point->value << " ";
13         point = point->next;
14     }
15     cout << endl;
16 }

  我们的链表创建以及打印已经没有问题了

四、链表长度
  链表的长度也可以用遍历解决:

 1 int SingleLinkedListLength(){
 2     SingleLinkedListNode *point = Shead;
 3     int len;
 4     while (point) {
 5         len++;
 6     }
 7     return len;
 8 }
 9 
10 int DoubleLinkedListLength(){
11     DoubleLinkedListNode *point = Dhead;
12     int len;
13     while (point) {
14         len++;
15     }
16     return len;
17 }

五、链表元素改值

  我们只需要把指针定位到元素上,再将它的value改变即可:

 1 void SingleLinkedListChange(int pos,int newvalue){
 2     SingleLinkedListNode *point = Shead;
 3     for (int i=0;i<=pos;i++) {
 4         point = point->next;
 5     }
 6     point->value = newvalue;
 7 }
 8 
 9 void DoubleLinkedListChange(int pos,int newvalue){
10     DoubleLinkedListNode *point = Dhead;
11     for (int i=0;i<=pos;i++) {
12         point = point->next;
13     }
14     point->value = newvalue;
15 }

六、链表插入

10------>20------->30
       ^
        |
       15

  我们想要插入15这个节点在10之后,于是我们将10的next项设为15,然后将15的next项设为20.注意,前面这段话如果用代码写出来是不对的(假设新插入节点的指针叫N,10的指针叫K):

K->next=N;N->next=K->next

  为什么不对呢,因为你如果先将10这个节点的下一个节点设为15,那15的下一个节点就又是15了——因为我们已经将10的下一个节点设为15,在将15的下一个节点设为10的下一个节点就没有任何意义了.所以上述代码应该反过来:

N->next=K->next;K->next=N

  而双向链表也是同样的,我们先设新插入节点的next与prev值,再设已有节点的prev与next值(假设新插入节点的指针叫N,10的指针叫K):

N->next = K->next;
N->prev = K;
k->next->prev = N;
k->next = N;

  好,把完整代码拿上来:

 1 void SingleLinkedListInsert(int pos,int newvalue){
 2     SingleLinkedListNode *point = Shead;
 3     for (int i=0;i<pos-1;i++) {
 4         point = point->next;
 5     }
 6     SingleLinkedListNode *node = new SingleLinkedListNode;
 7     node->value=newvalue;
 8     node->next = point->next;
 9     point->next = node;
10 }
11 
12 void DoubleLinkedListInsert(int pos,int newvalue){
13     DoubleLinkedListNode *point = Dhead;
14     for (int i=0;i<pos-1;i++) {
15         point = point->next;
16     }
17     DoubleLinkedListNode *node = new DoubleLinkedListNode;
18     node->value=newvalue;
19     node->next = point->next;
20     node->prev = point;
21     if (!point->next){
22         Dtail = node;
23     }
24     else{
25         point->next->prev = node;
26     }
27     if (!point->prev){
28         Dhead = node;
29     }
30     else{
31         point->next = node;
32     }
33 }

  注意在双向链表进行对表中已有元素的prev与next操作时,要判断prev与next是否为NULL

七、链表删除
  删除的原理与插入差不多,大家可以自己想想,这里不再阐述:

 1 void SingleLinkedListDelete(int pos){
 2     SingleLinkedListNode *point = Shead;
 3     for (int i=0;i<pos-1;i++) {
 4         point = point->next;
 5     }
 6     point->next = point->next->next;
 7 }
 8 
 9 void DoubleLinkedListDelete(int pos){
10     DoubleLinkedListNode *point = Dhead;
11     for (int i=0;i<pos;i++) {
12         point = point->next;
13     }
14     DoubleLinkedListNode *s1 = point->prev,*s2 = point->next;
15     if (s1!=NULL){
16         s1->next = s2;
17     }
18     else{
19         if (!pos){
20             Dhead = s2;
21         }
22         else{
23             Dhead = s1;
24         }
25     }
26     if (s2!=NULL){
27         s2->prev = s1;
28     }
29     else{
30         Dtail = s1;
31     }
32 }

八、链表元素查找
非常的简单,只要判断当前元素的值是否对应即可:

 1 bool SingleLinkedListFind(int pos,int findvalue){
 2     SingleLinkedListNode *point = Shead;
 3     for (int i=0;i<=pos;i++) {
 4         if (point->value==findvalue) return true;
 5         point = point->next;
 6     }
 7     return false;
 8 }
 9 
10 bool DoubleLinkedListFind(int pos,int findvalue){
11     DoubleLinkedListNode *point = Dhead;
12     for (int i=0;i<=pos;i++) {
13         if (point->value==findvalue) return true;
14         point = point->next;
15     }
16     return false;
17 }

九、结束语
好了,今天就到这里啦,如果这篇7500字的文章对你有帮助的话,请转发给更多的朋友一起学习,下期见(附完整代码)

  1 #include <iostream>
  2 using namespace std;
  3 
  4 struct SingleLinkedListNode{
  5     int value;
  6     struct SingleLinkedListNode *next;
  7 }*Shead=NULL,*Stail=NULL;
  8 
  9 struct DoubleLinkedListNode{
 10     int value;
 11     struct DoubleLinkedListNode *next;
 12     struct DoubleLinkedListNode *prev;
 13 }*Dhead=NULL,*Dtail=NULL;
 14 
 15 void CreateNewSingleLinkedList(int len){
 16     for (int i=0;i<len;i++){
 17         int inputvalue;
 18         cin >> inputvalue;
 19         SingleLinkedListNode *node = new SingleLinkedListNode;
 20         node->value = inputvalue;
 21         node->next = NULL;
 22         if (!Shead){Shead=node;Stail=node;}
 23         else{Stail->next=node;Stail=node;}
 24     }
 25 }
 26 
 27 void CreateNewDoubleLinkedList(int len){
 28     for (int i=0;i<len;i++){
 29         int inputvalue;
 30         cin >> inputvalue;
 31         DoubleLinkedListNode *node = new DoubleLinkedListNode;
 32         node->value = inputvalue;
 33         node->next = NULL;
 34         if (!Dhead){Dhead=node;Dtail=node;}
 35         else{Dtail->next=node;node->prev=Dtail;Dtail=node;}
 36     }
 37 }
 38 
 39 void OutputSingleLinkedList(){
 40     SingleLinkedListNode *point = Shead;
 41     while (point) {
 42         cout << point->value << " ";
 43         point = point->next;
 44     }
 45     cout << endl;
 46 }
 47 void OutputDoubleLinkedList(){
 48     DoubleLinkedListNode *point = Dhead;
 49     while (point) {
 50         cout << point->value << " ";
 51         point = point->next;
 52     }
 53     cout << endl;
 54 }
 55 
 56 int SingleLinkedListLength(){
 57     SingleLinkedListNode *point = Shead;
 58     int len;
 59     while (point) {
 60         len++;
 61     }
 62     return len;
 63 }
 64 
 65 int DoubleLinkedListLength(){
 66     DoubleLinkedListNode *point = Dhead;
 67     int len;
 68     while (point) {
 69         len++;
 70     }
 71     return len;
 72 }
 73 
 74 void SingleLinkedListChange(int pos,int newvalue){
 75     SingleLinkedListNode *point = Shead;
 76     for (int i=0;i<=pos;i++) {
 77         point = point->next;
 78     }
 79     point->value = newvalue;
 80 }
 81 
 82 void DoubleLinkedListChange(int pos,int newvalue){
 83     DoubleLinkedListNode *point = Dhead;
 84     for (int i=0;i<=pos;i++) {
 85         point = point->next;
 86     }
 87     point->value = newvalue;
 88 }
 89 
 90 void SingleLinkedListInsert(int pos,int newvalue){
 91     SingleLinkedListNode *point = Shead;
 92     for (int i=0;i<pos-1;i++) {
 93         point = point->next;
 94     }
 95     SingleLinkedListNode *node = new SingleLinkedListNode;
 96     node->value=newvalue;
 97     node->next = point->next;
 98     point->next = node;
 99 }
100 
101 void DoubleLinkedListInsert(int pos,int newvalue){
102     DoubleLinkedListNode *point = Dhead;
103     for (int i=0;i<pos-1;i++) {
104         point = point->next;
105     }
106     DoubleLinkedListNode *node = new DoubleLinkedListNode;
107     node->value=newvalue;
108     node->next = point->next;
109     node->prev = point;
110     if (!point->next){
111         Dtail = node;
112     }
113     else{
114         point->next->prev = node;
115     }
116     if (!point->prev){
117         Dhead = node;
118     }
119     else{
120         point->next = node;
121     }
122 }
123 
124 void SingleLinkedListDelete(int pos){
125     SingleLinkedListNode *point = Shead;
126     for (int i=0;i<pos-1;i++) {
127         point = point->next;
128     }
129     point->next = point->next->next;
130 }
131 
132 void DoubleLinkedListDelete(int pos){
133     DoubleLinkedListNode *point = Dhead;
134     for (int i=0;i<pos;i++) {
135         point = point->next;
136     }
137     DoubleLinkedListNode *s1 = point->prev,*s2 = point->next;
138     if (s1!=NULL){
139         s1->next = s2;
140     }
141     else{
142         if (!pos){
143             Dhead = s2;
144         }
145         else{
146             Dhead = s1;
147         }
148     }
149     if (s2!=NULL){
150         s2->prev = s1;
151     }
152     else{
153         Dtail = s1;
154     }
155 }
156 
157 bool SingleLinkedListFind(int pos,int findvalue){
158     SingleLinkedListNode *point = Shead;
159     for (int i=0;i<=pos;i++) {
160         if (point->value==findvalue) return true;
161         point = point->next;
162     }
163     return false;
164 }
165 
166 bool DoubleLinkedListFind(int pos,int findvalue){
167     DoubleLinkedListNode *point = Dhead;
168     for (int i=0;i<=pos;i++) {
169         if (point->value==findvalue) return true;
170         point = point->next;
171     }
172     return false;
173 }

标签:node,DoubleLinkedListNode,point,int,就够,next,链表,数据结构
From: https://www.cnblogs.com/AndyPomeloMars/p/16617960.html

相关文章

  • K8s小白?应用部署太难?看这篇就够了!
    在云原生趋势下,容器和Kubernetes可谓是家喻户晓,许多企业内部的研发团队都在使用Kubernetes打造DevOps平台。从最早的容器概念到Kubernetes再到DevOps/GitOps整个......
  • leetcode160:相交链表
    /***题目:*给你两个单链表的头节点headA和headB,请你找出并返回两个单链表相交的起始节点。*如果两个链表不存在相交节点,返回null。*注意......
  • 数据结构(java版)
    复杂度什么是算法算法是用于解决特定问题一系列执行步骤如果单从执行效率上进行评估,可能会想到这么一种方案比较不同算法对同一组输入的执行处理时间,这种叫事后统计法......
  • 什么是数据结构?
     数据结构是一种具有一定逻辑关系,在计算机中应用某种存储结构,并且封装了相应操作的数据元素的集合。--百度 数据结构用途:解决问题方法的效率,根数据的组织方式有......
  • Redis的底层数据结构
    SETname"xiaolincoding"OK>HSETpersonname"xiaolincoding"age180>RPUSHstu"xiaolin""xiaomei"(integer)4这些命令代表着:第一条命令:name是一个字......
  • Jedis操作redis中的数据结构
    哈希类型hash:map格式hsethgethgetAll /***hash数据结构操作*/@Testpublicvoidtest3(){//1、获取连接Jedisjedis=......
  • 数据结构开门篇
    数据结构1、什么是数据结构数据结构是数据组织、管理和存储格式,其使用目的是为了高效地访问和修改数据2、时间复杂度和空间复杂度什么是时间复杂度时间复杂度是对一......
  • Redis下载和安装和数据结构
    Redis下载和安装官网:https://redis.io官网打开的比较慢这边不建议使用官网建议使用中文网中文网:https://www.redis.net.cn下载完成解压可以直接使用redis.windows.......
  • redis数据结构介绍和redis命令操作_string&hash
    redis的数据结构redis存储的是:key,value格式的数据,其中key都是字符串,value有物种不同的数据结构value的数据结构:字符串类型string哈希类型hash:map格式列表类型......
  • redis核心数据结构与高性能原理
    一:redis安装1.下载wgethttp://download.redis.io/releases/redis-5.0.3.tar.gz 2.解压和编译tarxzfredis‐5.0.3.tar.gzcdredis‐5.0.3#进入到解压好的re......