数据结构——双向链表的实现

双向链表主要为了解决单链表找前驱的问题。除了插入、删除操作之外,其他操作与单链表都相同。因此这里只是比较简单的写了双向链表的插入和删除操作。画出结点结构图的话,思路会很清晰,线性表这块还算是比较简单的能够实现。

  1 /*
  2     在单链表中,求后继的方法NextElem执行的时间为O(1),求前驱的方法PriorElem执行的时间为O(n),
  3     引入双向链表就是为了克服单链表这种单向性的缺点。
  4 */
  5
  6 #include<stdio.h>
  7 #include<stdlib.h>
  8
  9 //定义存储类型
 10 typedef int ElemType;
 11
 12 //双向链表的存储结构
 13 typedef struct DuLNode{
 14     ElemType data;
 15     DuLNode *next;
 16     DuLNode *prior;
 17 }DuLNode, *DuLinkList;
 18
 19 //声明,指针函数
 20 void(*visit)(DuLNode *node);
 21
 22 //声明,辅助函数
 23 void visitData(DuLNode *node);
 24
 25 //对双向链表的基本操作
 26 bool InitDuLinkList(DuLinkList &L);    //    初始化一个空表
 27 DuLinkList GetLNode(DuLinkList L, int i);    //返回第i个结点
 28 void ListTraverse(DuLinkList L, void(visit(DuLNode *node)));    //遍历双向链表
 29 void ListInsert(DuLinkList &L, int i, ElemType e);    //在第i个结点之前插入,数据域是e的结点
 30 void AppendLast(DuLinkList &L, ElemType e);    //在最后一个结点之后插入,数据域是e的结点
 31 void ListDelete(DuLinkList &L, int i, DuLinkList &rNode);    //删除第i个结点并返回
 32
 33 //测试模块
 34 int main(){
 35
 36     DuLinkList L;
 37     InitDuLinkList(L);
 38     for (int i = 1; i <= 6; i++)
 39         AppendLast(L, i);
 40     ListTraverse(L, visitData);
 41     printf("\n");
 42
 43     printf("第一个元素的后继是:%d\n", GetLNode(L, 1)->next->data);
 44     printf("第一个元素的前驱是:%d\n", GetLNode(L, 1)->prior->data);
 45     printf("最后一个元素的前驱是:%d\n", GetLNode(L, 6)->prior->data);
 46     printf("\n");
 47
 48     ListInsert(L, 1, 7);
 49     ListTraverse(L, visitData);
 50     printf("第一个元素的后继是:%d\n", GetLNode(L, 1)->next->data);
 51     printf("第一个元素的前驱是:%d\n\n", GetLNode(L, 1)->prior->data);
 52
 53     DuLNode *rNode;
 54     ListDelete(L, 7, rNode);
 55     ListTraverse(L, visitData);
 56     printf("最后一个元素的前驱是:%d\n", GetLNode(L, 6)->prior->data);
 57     ListDelete(L, 1, rNode);
 58     ListTraverse(L, visitData);
 59     printf("第一个元素的后继是:%d\n", GetLNode(L, 1)->next->data);
 60     printf("第一个元素的前驱是:%d\n\n", GetLNode(L, 1)->prior->data);
 61
 62     system("pause");
 63     return 0;
 64 }
 65
 66 //各函数定义模块
 67 void visitData(DuLNode *node){
 68     printf("%4d", node->data);
 69 }
 70
 71 bool InitDuLinkList(DuLinkList &L){    //    初始化一个空表
 72     L = (DuLinkList)malloc(sizeof(DuLNode));
 73     if (!L)
 74         return false;
 75     L->prior = NULL;
 76     L->next = NULL;
 77     return true;
 78 }
 79
 80 DuLinkList GetLNode(DuLinkList L, int i){    //返回第i个结点的值
 81     int j = 1;
 82     DuLNode *p = L->next;
 83
 84     //找第i个结点
 85     while (p && j != i){
 86         p = p->next;
 87         j++;
 88     }
 89
 90     if (j > i || !p){
 91         printf("\n不存在该结点!\n");
 92         return L;
 93     }
 94
 95     return p;
 96 }
 97
 98 void ListTraverse(DuLinkList L, void(visit(DuLNode *node))){    //遍历单链表
 99     DuLNode *p = L->next;
100     while (p){
101         visit(p);
102         p = p->next;
103     }
104     printf("\n");
105 }
106
107 void ListInsert(DuLinkList &L, int i, ElemType e){    //在第i个结点之前插入,数据域是e的结点
108     DuLNode *p = GetLNode(L, i);
109     if (!p){
110         printf("没找到该元素,不能进行插入!\n");
111         return;
112     }
113
114     DuLNode *s = (DuLinkList)malloc(sizeof(DuLNode));
115     if (!s)
116         return;
117     s->data = e;
118     s->next = p;
119     p->prior->next = s;
120     s->prior = p->prior;
121     p->prior = s;
122 }
123
124 void AppendLast(DuLinkList &L, ElemType e){    //在最后一个结点之后插入,数据域是e的结点
125     //找到最后一个结点
126     DuLNode *p = L;
127     while (p->next){
128         p = p->next;
129     }
130     //新建一个结点
131     DuLNode *newNode = (DuLinkList)malloc(sizeof(DuLNode));
132     if (!newNode)
133         return;
134     newNode->data = e;
135     //插入
136     newNode->next = p->next;
137     p->next = newNode;
138     newNode->prior = p;
139 }
140
141 void ListDelete(DuLinkList &L, int i, DuLinkList &rNode){    //删除第i个结点并返回
142     DuLNode *p = GetLNode(L, i);
143     if (!p){
144         printf("没找到该元素,不能进行删除!\n");
145         return;
146     }
147
148     p->prior->next = p->next;
149     if (p->next){
150         p->next->prior = p->prior;
151         p->next = NULL;
152         p->prior = NULL;
153     }
154
155     rNode = p;
156     free(p);
157 }

不积跬步,无以至千里;不积小流,无以成江海。坚持着。

时间: 2024-10-21 20:32:16

数据结构——双向链表的实现的相关文章

数据结构 双向链表 C语言实现

dlist.h 1 #ifndef __dList_H 2 #define __dlist_H 3 4 typedef int Item; 5 typedef struct Node *PNode; 6 typedef PNode Position; 7 /*定义节点类型*/ 8 typedef struct Node 9 { 10 Item data; /*数据域*/ 11 PNode previous; /*指向前驱*/ 12 PNode next; /*指向后继*/ 13 }Node; 1

数据结构-双向链表

为了解决对链表操作的灵活性,把单链表的单一指向改为双向驱动,从而形成双向链表.Java的LinkedList就是双向链表的实现,但是因为有双端队列的成分,显得有些不单纯. ■双向链表的节点定义 private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = ele

Linux内核分析--内核中的数据结构双向链表续【转】

在解释完内核中的链表基本知识以后,下面解释链表的重要接口操作: 1. 声明和初始化 实际上Linux只定义了链表节点,并没有专门定义链表头,那么一个链表结构是如何建立起来的呢?让我们来看看LIST_HEAD()这个宏: #define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name) 需要注意的是,Linux 的每个双循

喜羊羊系列之数据结构双向链表

博客:http://blog.csdn.net/muyang_ren 关于双向链表的原理很多都有说明,我这只是与前面的内核链表作个对比,同样实现数据的增删差改. 截图: 1.main.c #include "doublelist.h" int main(void) { int num, i; double_plist list; doublelist_init(&list); //初始化双向链表 printf("\n请输入链表长度:"); scanf(&qu

数据结构 - 双向链表(C++)

// ------DoublyLinkedList.h------ template <class T> class DNode { private: // 指向左.右结点的指针 DNode<T> * left; DNode<T> * right; public: // data为公有成员 T data; // 构造函数 DNode(void); DNode(const T& item); // 改变表的方法 void InsertRight(DNode<

C实现通用数据结构--双向链表

双向链表概述 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继next和直接前驱prev.所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点.为了标识链表的头和尾,将第一个元素的prev指针和最后一个元素的next指针设置为NULL 要反向遍历整个双向链表,使用prev指针从尾到头的顺序访问各个元素,因此为每个元素增加了一个指针的代价,换来的是双向链表更加灵活的访问. 本文地址:http://www.cnblogs.com/archi

Python数据结构--双向链表

1 ''' 2 双向链表包含第一个和最后一个的链接元素. 3 每个链接都有一个数据字段和两个称为next和prev的链接字段. 4 每个链接都使用其下一个链接与其下一个链接链接. 5 每个链接都使用其上一个链接与之前的链接链接. 6 最后一个链接将链接作为空来标记列表的结尾. 7 ''' 8 9 10 # 创建节点 11 class Node(): 12 def __init__(self, data): 13 self.data = data 14 self.next = None 15 se

Java数据结构——双向链表

什么是双向链表?每一个结点不仅配有next引用,同时还有一个prev引用,指向其上一个结点(前驱结点), 没有前驱的时候就为NULL. (以下图片均来自网络,侵删) 与单链表的区别?和单向链表相比有以下优势: 插入删除不需要移动元素外,可以原地插入删除 可以双向遍历 插入操作 删除操作 实现 public class DLNode { Object data; DLNode prev; DLNode next; static DLNode head; static DLNode tail; //

算法导论第十章数据结构--双向链表

看的概念挺朦胧的,没有明确好双链表到底需要哪些方法,其实针对这种结构应该可以写很多方法,并没有什么特定标准. 不过真是只看不练不行啊,一下手各种错误,各种溢出 #include<iostream> using namespace std; template<class T> struct Node { T value; Node<T>* pre; Node<T>* next; }; template<class T> class Flist {