双向链表

C++实现单向链表,双向链表,单向环形链表,双向环形链表 本文讲解了链表的四种类型以及数据结构,同时给出了四种链表的C++代码实现。 阅读详情

http://www.cprogramming.com/snippets/source-code/double-linked-list-cplusplus


This snippet submitted by Ali Murad on 2012-03-10. It has been viewed 3838 times.
Rating of 9 with 20 votes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//An example of a simple double linked list using OOP techniques
#include <iostream>
using namespace std;
 
struct Node
{
   double value;
   Node *N,*P;
   Node( double y)
   {
       value = y;
       N = P = NULL;
   }
};
 
class doubleLinkedList
{
   Node *front;
   Node *back;
   public :
   doubleLinkedList()
   {  front = NULL; back = NULL; }
   ~doubleLinkedList(){ destroyList();}
   void appendNodeFront( double x);
   void appendNodeBack( double x);
   void dispNodesForward();
   void dispNodesReverse();
   void destroyList();
};
 
void doubleLinkedList::appendNodeFront( double x)
   {
         Node *n = new Node(x);
         if ( front == NULL)
         {
             front = n;
             back = n;
         }
         else
         {
             front->P = n;
             n->N = front;
             front = n;
         }
   }
   void doubleLinkedList::appendNodeBack( double x)
   {
         Node *n = new Node(x);
         if ( back == NULL)
         {
             front = n;
             back = n;
         }
         else
         {
             back->N = n;
             n->P = back;
             back = n;
         }
 
   }
 
   void doubleLinkedList::dispNodesForward()
   {
       Node *temp = front;
       cout << "\n\nNodes in forward order:" << endl;
       while (temp != NULL)
       {
          cout << temp->value << "   " ;
          temp = temp->N;
       }
   }
   void doubleLinkedList::dispNodesReverse()
   {
       Node *temp = back;
       cout << "\n\nNodes in reverse order :" << endl;
       while (temp != NULL)
       {
          cout << temp->value << "   " ;
          temp = temp->P;
       }
   }
void doubleLinkedList::destroyList()
{
     Node *T = back;
     while (T != NULL)
     {
         Node *T2 = T;
         T = T->P;
         delete T2;
     }
     front = NULL;
     back = NULL;
}
int main()
{
     doubleLinkedList *list = new doubleLinkedList();
     //append nodes to front of the list
     for ( int i = 1 ; i < 4 ; i++)
     list->appendNodeFront(i*1.1);
 
     list->dispNodesForward();
     list->dispNodesReverse();
 
     //append nodes to back of the list
     for ( int i = 1 ; i < 4 ; i++)
     list->appendNodeBack(11.0 - (1.1 * i));
     cout << endl << endl;
     list->dispNodesForward();
     list->dispNodesReverse();
 
     cout << endl << endl;
     delete list;
     return 0;
}
 
/* Program's output
Nodes in forward order:
3.3   2.2   1.1
 
Nodes in reverse order :
1.1   2.2   3.3
 
 
 
Nodes in forward order:
3.3   2.2   1.1   9.9   8.8   7.7
 
Nodes in reverse order :
7.7   8.8   9.9   1.1   2.2   3.3
*/






转自:

http://blog.youkuaiyun.com/feixiaoxing/article/details/6849457


【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】


    前面的博客我们介绍了单向链表。那么我们今天介绍的双向链表,顾名思义,就是数据本身具备了左边和右边的双向指针。双向链表相比较单向链表,主要有下面几个特点:

    (1)在数据结构中具有双向指针

    (2)插入数据的时候需要考虑前后的方向的操作

    (3)同样,删除数据的是有也需要考虑前后方向的操作

    那么,一个非循环的双向链表操作应该是怎么样的呢?我们可以自己尝试一下:

    (1)定义双向链表的基本结构

  1. typedef struct _DOUBLE_LINK_NODE  
  2. {  
  3.     int data;  
  4.     struct _DOUBLE_LINK_NODE* prev;  
  5.     struct _DOUBLE_LINK_NODE* next;  
  6. }DOUBLE_LINK_NODE;  
     (2)创建双向链表节点
  1. DOUBLE_LINK_NODE* create_double_link_node(int value)  
  2. {  
  3.     DOUBLE_LINK_NODE* pDLinkNode = NULL;  
  4.     pDLinkNode = (DOUBLE_LINK_NODE*)malloc(sizeof(DOUBLE_LINK_NODE));  
  5.     assert(NULL != pDLinkNode);  
  6.   
  7.     memset(pDLinkNode, 0, sizeof(DOUBLE_LINK_NODE));  
  8.     pDLinkNode->data = value;  
  9.     return pDLinkNode;  
  10. }  
     (3)删除双向链表
  1. void delete_all_double_link_node(DOUBLE_LINK_NODE** pDLinkNode)  
  2. {  
  3.     DOUBLE_LINK_NODE* pNode;  
  4.     if(NULL == *pDLinkNode)  
  5.         return ;  
  6.   
  7.     pNode = *pDLinkNode;  
  8.     *pDLinkNode = pNode->next;  
  9.     free(pNode);  
  10.     delete_all_double_link_node(pDLinkNode);  
  11. }  
     (4)在双向链表中查找数据
  1. DOUBLE_LINK_NODE* find_data_in_double_link(const DOUBLE_LINK_NODE* pDLinkNode, int data)  
  2. {  
  3.     DOUBLE_LINK_NODE* pNode = NULL;  
  4.     if(NULL == pDLinkNode)  
  5.         return NULL;  
  6.   
  7.     pNode = (DOUBLE_LINK_NODE*)pDLinkNode;  
  8.     while(NULL != pNode){  
  9.         if(data == pNode->data)  
  10.             return pNode;  
  11.         pNode = pNode ->next;  
  12.     }  
  13.       
  14.     return NULL;  
  15. }  
     (5)双向链表中插入数据
  1. STATUS insert_data_into_double_link(DOUBLE_LINK_NODE** ppDLinkNode, int data)  
  2. {  
  3.     DOUBLE_LINK_NODE* pNode;  
  4.     DOUBLE_LINK_NODE* pIndex;  
  5.   
  6.     if(NULL == ppDLinkNode)  
  7.         return FALSE;  
  8.   
  9.     if(NULL == *ppDLinkNode){  
  10.         pNode = create_double_link_node(data);  
  11.         assert(NULL != pNode);  
  12.         *ppDLinkNode = pNode;  
  13.         (*ppDLinkNode)->prev = (*ppDLinkNode)->next = NULL;  
  14.         return TRUE;  
  15.     }  
  16.   
  17.     if(NULL != find_data_in_double_link(*ppDLinkNode, data))  
  18.         return FALSE;  
  19.   
  20.     pNode = create_double_link_node(data);  
  21.     assert(NULL != pNode);  
  22.   
  23.     pIndex = *ppDLinkNode;  
  24.     while(NULL != pIndex->next)  
  25.         pIndex = pIndex->next;  
  26.   
  27.     pNode->prev = pIndex;  
  28.     pNode->next = pIndex->next;  
  29.     pIndex->next = pNode;  
  30.     return TRUE;  
  31. }  
     (6)双向链表中删除数据
  1. STATUS delete_data_from_double_link(DOUBLE_LINK_NODE** ppDLinkNode, int data)  
  2. {  
  3.     DOUBLE_LINK_NODE* pNode;  
  4.     if(NULL == ppDLinkNode || NULL == *ppDLinkNode)  
  5.         return FALSE;  
  6.   
  7.     pNode = find_data_in_double_link(*ppDLinkNode, data);  
  8.     if(NULL == pNode)  
  9.         return FALSE;  
  10.   
  11.     if(pNode == *ppDLinkNode){  
  12.         if(NULL == (*ppDLinkNode)->next){  
  13.             *ppDLinkNode = NULL;  
  14.         }else{  
  15.             *ppDLinkNode = pNode->next;  
  16.             (*ppDLinkNode)->prev = NULL;  
  17.         }  
  18.   
  19.     }else{  
  20.         if(pNode->next)  
  21.             pNode->next->prev = pNode->prev;  
  22.         pNode->prev->next = pNode->next;  
  23.     }  
  24.   
  25.     free(pNode);  
  26.     return TRUE;  
  27. }  
     (7)统计双向链表中数据的个数
  1. int count_number_in_double_link(const DOUBLE_LINK_NODE* pDLinkNode)  
  2. {  
  3.     int count = 0;  
  4.     DOUBLE_LINK_NODE* pNode = (DOUBLE_LINK_NODE*)pDLinkNode;  
  5.   
  6.     while(NULL != pNode){  
  7.         count ++;  
  8.         pNode = pNode->next;  
  9.     }  
  10.     return count;  
  11. }  
     (8)打印双向链表中数据
  1. void print_double_link_node(const DOUBLE_LINK_NODE* pDLinkNode)  
  2. {  
  3.     DOUBLE_LINK_NODE* pNode = (DOUBLE_LINK_NODE*)pDLinkNode;  
  4.   
  5.     while(NULL != pNode){  
  6.         printf("%d\n", pNode->data);  
  7.         pNode = pNode ->next;  
  8.     }  
  9. }  
    注意:

        今天我们讨论的双向链表是非循环的,大家可以考虑一下如果改成循环双向链表,应该怎么写?如果是有序的循环双向链表,又该怎么写?


转自:

http://jpkc.xaau.edu.cn/sjjg/datastru/zxxx/two%20lesson/233.html

双向链表

    双向链表是链式存储结构的另一种表示形式。在双向链表中,结点的结构如图2-13所示。

1

图2-13 双向链表结点结构示意

    从图2-13可以看到,双向链表中每个结点包括三个域:数据域(data),前趋指针域(prior),后继指针域(next)。数据域(data)用来存放该结点的数据元素信息;前趋指针域(prior)用来存放指示该结点的直接前趋的地址信息,即前趋指针;后继指针域(next)用来存放指示该结点的直接后继的地址信息,即后继指针。前趋指针同后继指针分别构成两个不同方向的链。若每条链构成一个环,就称为双向循环链表,如图2-14所示。

1

图2-14  双向循环链表

    在单链表或单向循环链表中,若指针指向某结点后,要通过该结点访问其直接后继很方便,而要通过该结点求其直接前趋,则需从头指针出发,这是由它们的单向性决定的。有了双向链表后,这个问题就变得相当容易了,因为每个结点直接前趋的地址就包含在其前趋指针域中。 双向链表的类C语言可描述如下:

结构2-3 双向链表

struct dubnode

 { Datatype data;

   struct dubnode *prior;

   struct dubnode *next;

}

typedef  struct  dubnode  DuLinkList;

    双向链表的某些操作将涉及到两个方向的指针修改,操作时应特别注意。图2-15是在双向链表中插入一个结点的示意图。

1

图2-15 在双向链表中插入一个结点

    针修改操作为:

                s->prior = p->prior;

                s->next = p;

                p->prior->next = s;

                p->prior = s;

    以上操作的语句顺序可以改变,但要注意p的前趋指针的修改一定要在p的前趋结点的后继指针修改之后方可修改,否则不能正确插入。

同样,在双向链表中删除一个结点时,也需要修改两个方向的指针,其指针变化如图2-16所示。

1

图2-16 在双向链表中删除一个结点

指针修改操作为:

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

               p->next->prior = p->prior; 请考虑以上操作的语句顺序是否可以改变。

在双向链表中,若p为指向表中某一结点的指针,则有:

               p->next->prior = p;

               p->prior->next = p;

这正好反映了双向链表的结构特性。





双向链表详解 注意:这⾥的“带头”跟前⾯我们说的“头结点”是两个概念,实际前⾯的在单链表阶段称呼不严 谨,但是为了同学们更好的理解就直接称为单链表的头结点。在单链表中我们会去说头节点,并不是意思是说,单链表是带头链表,而是指的是单链表的第一个节点,方便理解而已。双向链表和单链表的区别在于:双向链表有哨兵位,也就是带头,我们在扩容的时候需要传一个无效的数据去占位。单链表是单向的所以只有指向下一节点的指针,而双向链表是双向的所以还要包括指向前一节点的指针。:数据+指向下一节点的指针+指向前一个节点的指针。 阅读详情

相关推荐

机器视觉/将HIK海康面阵相机连接Halcon软件

本文简述了如何将海康面阵相机连接到Halcon软件中进行实时取图的过程。

Dahe.qu 4866

循环双链表加目录IO实现简单的文件检索

#include"stdio.h" #include"stdlib.h" #include"fcntl.h" #include"dirent.h" #include"string.h" typedef struct doublelink { char name[20]; struct doublelink *front; struct doublelink *frev; }dl; dl *he

zhouxf的专栏 3194

RK3588与银河麒麟V10 SP1 2403深度适配:国产化硬件与操作系统的完美融合

本文深入探讨了RK3588处理器与银河麒麟V10 SP1 2403操作系统的深度适配,展示了国产化硬件与操作系统的完美融合。通过性能验证和实际应用测试,证明了这套组合在多媒体处理、AI推理和日常办公中的卓越表现,实现了完全自主可控的计算平台。

weixin_29194255的博客 248

c语言双向链表重组写法,一个C语言做的双向链表程序,请高手帮忙改错

#include #include #include typedef bool Status;typedef int HeadEType;#define OK 1#define ERROR 0typedef struct{int num; //存放学号char name[10]; //存放姓名}EType;typedef struct Doub...

weixin_36216860的博客 230

【实战指南】OpenClaw Telegram 群聊不响应完整解决方案:从获取群 ID 到关闭隐私模式全流程

将整个从“获取群组 ID → 配置 OpenClaw Telegram 通道 → 关闭隐私模式 → 测试”的全流程都整合进去。

hampeter的博客 3486

ADS新手必看:ICCAP数据导入与导出CSV的完整流程(附常见问题解决)

本文为ADS新手详细讲解了如何将ICCAP测试数据导入ADS进行仿真分析,并导出为通用CSV格式的完整流程。内容涵盖文件格式解析、导入设置、数据验证、处理技巧及常见问题排查,重点解决了数据文件导入过程中的兼容性与单位映射等核心难点,帮助射频工程师高效连接测量与仿真环节。

peace的博客 557

图的遍历记(深度和广度优先搜索—BFS&&DFS)的笔记

图的最基本的两种遍历方法,参考了算法导论的两个图例。 最值得说的是: 广度优先搜索(BFS)跟树的层次遍历比较像 用了队列(Queue)来作为临时储存的媒介。 深度优先搜索(DFS)跟输的前序遍历比较像——>(preoder traversal)。 先是广度优先搜索的图例: 然后上代码 以后补充w: 先是链表形式的: #include #include

loppolloppol的专栏 1000

西瓜书第二章——模型评估与选择(十折交叉验证/查准查全F1)

第二章——模型评估与选择

xsddys的博客 953

什么是双向链表,一篇搞懂双向链表

双向链表,python3

hahaha_1112的博客 1970

最小可分辨对比度(MRC)

最小可分辨对比度的测试方法如下: 1)选择对比度测试靶板,一般有100%,50%,33.77%,15%,5%。 2)调整照度,确保能够清晰观测到图像中的靶标; 3)利用USAF1951分辨率靶观察找到能够分辨出的靶标。 1951 USAF分辨力测试图目前仍广泛地应用于测试光学成像系统(如显微镜和相机)的分辨能力。这种图案包括几组由三条短线构成组合,短线的尺寸从大到小。成像系统无法辩明的...

6272

YOLOv8改进 | Conv篇 | DWRSeg扩张式残差助力小目标检测 (附修改后的C2f+Bottleneck)

本文内容给大家带来的DWRSeg中的DWR模块来改进YOLOv8中的C2f和Bottleneck模块,主要针对的是小目标检测,主要创新点可以总结如下:多尺度特征提取机制的深入研究和创新的DWR模块和SIR模块的提出这种方法使得网络能够更灵活地适应不同尺度的特征,从而更准确地识别和分割图像中的物体。通过本文你能够了解到DWRSeg的基本原理和框架,并且能够在你自己的网络结构中进行添加(DWRSeg需要增加一定的计算量一个DWR模块大概增加0.4GFLOPs)。

Snu77的博客 9570

【数据结构】之双向链表、双端(双向)链表、循环(双向)链表

双向链表、双端(双向)链表、循环(双向)链表示意(简)图: 声明:下面各图中,箭头指向的是整个节点,而不是指向节点中的prior或next。 双向链表:只有一个指针指向最开始的结点。 双端(双向)链表:有两个指针分别指向两端的节点。 循环(双向)链表:指向形成一个闭环。 双端(双向)链表的Java实现(简单示例): 注:双向链表、双端(双向)链表、循环(双向)链表的实现思路...

JustryDeng 2211

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

双向链表的实现

本文主要介绍了双向链表的结构,概念,相关接口的具体实现方法和链表与顺序表的区别, 并简要介绍了哨兵位的含义与作用。

2303_81060385的博客 1243

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

数据结构——双向链表(双向连接的图解、双向链表的创建、操作双向链表)

举个例子: 假设一个文本编辑用链表来存储文本. 每一行用一个String对象存储在链表的一个节点中. 当编辑器用户向下移动光标时, 链表直接操作到下一个节点即可. 但是当用于将光标向上移动呢?- 我们可以轻松的到达下一个节点, 但是回到前一个节点是很难的. 但是, 在实际开发中, 经常会遇到需要回到上一个节点的情况。- 也就是链表相连的过程是单向的. 实现的原理是上一个链表中有一个指向下一个的引用.- 一个节点既有向前连接的引用, 也有一个向后连接的引用.- 既可以从头遍历到尾, 又可以从尾遍历到头。

qq_52301431的博客 4575

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

【双向链表】数据结构双向链表的实现

双向链表的实现

m0_56069910的博客 2196

双向链表和双向循环链表

1.创建一个新结点2.遍历链表找到最后一个结点p3.p结点的后继指针指向新结点,新结点的前驱指针指向p,新结点的后继指针指向NULL;void Insert_tail(DLIST head, DLIST node)\\尾部插入= NULL)void Show(DLIST head)\\打印链表while (p!= NULL)int main()\\运行Show(head);return 0;

weixin_63082397的博客 1015

第2章 双向链表

对链表而言,双向均可遍历是最方便的,另外首尾相连循环遍历也可大大增加链表操作的便捷性。因 此,双向循环链表,是在实际运用中是最常见的链表形态。

m0_74916669的博客 945

数组实现双向链表、双向链表的操作

分析: 思路: 遍历:和单链表一样,只是可以向前,也可以向后查找。 添加(默认添加到双向链表的最后) (1).先找到双向链表的最后这个节点(temp) (2).temp.next = newHeroNode (3).newHeroNode.pre = temp; 修改思路和单链表一样 删除 (1).以为是双向链表,因此,我们可以实现自我删除某个节点 (2).直接找到要删除的这个节点,比...

qq_40823802的博客 2011

特殊的链表——双向链表

一、双向链表的概述 1、双向链表的定义:在单链表的每个结点里再增加一个指向其直接前驱的指针域prior,这样链表中就形成了有两个方向不同的链,故称为双向链表。 2、优点:双向链表可以克服单链表查找链表中某结点不方便的缺点。 3、双向循环链表:和单链的循环表类似,双向链表也可以有循环表。让头结点的前驱指针指向链表的最后一个结点,让最后一个结点的后继指针指向头结点。 二、双向链表的特点与算法操作 1、双向链表结构的对称性:设指针P指向某一结点,侧有: p->next->prior=p=p

kxbdys的博客 4419

双向链表的双向遍历

双向链表的双向遍历 双向链表相比较于单向链表的优势之一就是可以快速遍历,对于单向链表只能借助于单个指针逐个遍历,而对于双向链表而言因为每个节点都存在一个前指针和后指针,所以可以借助于两个指针双向遍历,相对于单向链表而言可以节省很多时间。但是对于双向链表的双向遍历需要考虑的因素偏多,代码的步骤需要非常严谨。对于两个指针而言需要考虑节点数是奇数还是偶数,若是奇数,要考虑两指针相遇的情况,只需要输出其中...

A___jay的博客 3888

【C++】双向链表

前言: 前面我们实现了 单向链表 ,也发现了它的一些局限性。 比如说: ∙\bullet∙ 查找方向只能是单向的,每次只能从头查到尾 ∙\bullet∙ 对于删除操作,它必须借助辅助节点帮助进行删除 所以为了克服这些缺点,我们引出了双向链表。 一.基本介绍 双向链表它的方向是双向的,相对于单向链表它可以实现自我删除。 双向链表的节点包含三个量,首先一个还是节点信息data,还有指向下一个节点地址的next指针,最后添加了指向前一个节点地址的pre指针。 实现思路: ∙\bullet.

taoxing 2525
上一篇: [入門級] 如何用 Mac OS X 的 Xcode 寫 C 語言程式
下一篇: Reverse a linked list
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值