数据结构双向链表共16页文档

合集下载

双向链表01

双向链表01

双向链表01
双向链表:在单链表的每个结点⾥再增加⼀个指向其前驱的指针域 prior,这样链表中就形成了有两个⽅向不同的链,故称其为“双向链表”。

双向链表的结构定义:
typedef struct DuLnode{
Elemtype data;
struct DuLNode *prior, *next;
} DuLNode, *DuLinkList;
双向循环链表:和单链的循环表类似,双向链表也可以有循环表:
①让头结点的前驱指针指向链表的最后⼀个结点;
②让最后⼀个结点的后继指针指向头结点。

双向链表结构的对称性(设指针 p 指向某⼀节点)
p -> proior ->next = p = p -> next -> prior
意思是指针 p 指向结点的前⼀个结点的后边那个节点,就是指针 p 指向的结点本⾝;
⽽ “p -> next -> prior” 意思则是,指针 p 所指向结点的后⼀个结点的前⼀个结点,⾃然也是指针 p 所指向结点。

在双向链表中有些操作(如:ListLength,GetElem等),因仅涉及⼀个⽅向的指针,故它们的算法与线性链表的相同。

但在插⼊、删除时,则需同时修改两个⽅向上的指针,两者操作的时间服早读均为 O(n)。

数据结构双向链表-推荐下载

数据结构双向链表-推荐下载

二〇一二 年
//头文件 #define Student EType #define HeadEType int #include<iostream.h> #include <stdlib.h> #include<string.h> #include<iomanip.h> //以下是数据类型的定义 struct Student {
实验项目 1:线性表存储及运算
学 号
实验地点
评语:数据结构实验报告ຫໍສະໝຸດ 数据结构《实验 1》实验报告
姓 名
指导教师
按时完成实验;实验内容和过程记录完整;回答问题完整、
正确;实验报告的撰写认真、格式符合要求;无抄袭的行为。
线性表链式存储(双向链表)插入、删除运算
1、预习要求:线性表的插入、删除相关概念及运算,完成线性表元素的插入、删除。 2、实验目的: (1)了解线性表的插入、删除相关概念; (2)理解线性表的插入、删除过程和结构定义; (3)掌握算法转换为程序的过程中的变化。 3、实验内容及要求: (1)分别建立包含 10 个数据元素的链式存储线性表; (2)从键盘输入一个数据元素,插入到线性表中第 k(包含 0 号位置)个位置; (3)从键盘输入一个数据元素关键字或位置 k(包含 1 号位置),从线性表中删除相应 数据元素; (4)给出程序及插入、删除前和插入、删除后线性表结果。 4、实验设备(环境)及要求 硬件:支持 Intel Pentium Ⅱ及其以上 CPU ,内存 128MB 以上、硬盘 1GB 以上容量 的微机。 软件:配有 Windows98/2000/XP 操作系统,安装 Visual C++ 。 5、实验时间:6 学时 6、该文档的文件名不要修改,存入<学号> <姓名> 命名的文件夹中 7、该表中的数据只需填空,已有内容不要修改

数据结构学习(C )双向链表

数据结构学习(C  )双向链表

数据结构学习(C++)——双向链表happycock(原作)转自CSDN原书这部分内容很多,至少相对于循环链表是很多。

相信当你把单链表的指针域搞清楚后,这部分应该难不倒你。

现在我的问题是,能不能从单链表派生出双向链表?<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />你可以有几种做法:一种就是先定义一个双链节点——但是,它的名字必须叫Node,这是没办法的事;不然你就只好拷贝一份单链表的实现文件,把其中的Node全都替换成你的双链节点名字,但是这就不叫继承了。

另一种做法就是先定义一种结构例如这样的:template <class Type> class newtype{public:Type data;Node<newtype> *link;}当你派生双向链表时,这样写template <calss Type> class DblList : public List<newtype<Type> >,注意连续的两个“>”之间要有空格。

或者根本不定义这样的结构,直接拿Node类型来做,例如我下面给出的。

但是,请注意要完成“==”的重载,否则,你又要重写Find函数,并且其他的某些操作也不方便。

在开始完成你的从单链表派生出来的双向链表之前,要在单链表这个基类中添加修改当前指针和当前前驱指针的接口,如下所示:protected:void Put(Node<Type> *p)//尽量不用,双向链表将使用这个完成向前移动{current = p;}void PutPrior(Node<Type> *p)//尽量不用,原因同上{prior = p;}因为这个接口很危险,而且几乎用不到,所以我在前面并没有给出,但要完成双向链表最“杰出”的优点——向前移动当前指针,必须要使用。

图文详解双向链表原理

图文详解双向链表原理

图⽂详解双向链表原理
双向链表的主要优点是对于任意给的结点,都可以很轻易的获取其前结点和后结点,其主要缺点是每个结点需要保存next和prev两个属性,因此需要更多的空间开销,同时结点的插⼊与删除操作也将更加耗时,因为需要操作更多的指向操作。

双向链表单个节点结构:
双向链表节点
双向链表的数据结构:
双向链表数据结构
双向链表的插⼊操作
插⼊数据到链表尾部
链表尾部插⼊数据
插⼊数据到链表中间
链表中部插⼊数据
双向列表删除操作
删除链表尾部数据
删除尾部数据
删除链表中间数据
删除中间数据
循环双向列表设计
循环双向链表是在普通双向链表基础上进化得到的。

在普通的双向链表中,如果我们要获取最后⼀个节点的时候,我们只能从头开始遍历,⼀直遍历到最后才能够拿到最后⼀个节点的数据。

⽽循环双向链表会把header的prev指向最后⼀个节点,最后⼀个节点next指向header。

其数据结构如图所⽰:
循环双向链表
循环链表的添加、删除和普通的双向链表是⼀模⼀样的,这⾥就不再赘述。

数据结构-双向链表

数据结构-双向链表

bool InsertTailBList(BList phead,int x) { assert(phead != NULL); BNode* p=BuyNode(x); phead->front->last=p; p->front=phead->front; phead->front=p; p->last=phead; return true; } bool DeleteBList(BList phead,int x) { assert(phead!= NULL); BNode* p=SearchBList(phead,x); BNode* q=NULL; if(p != NULL) { q=p->front; p->last->front=q; q->last=p->last; free(p); return true; } return false; } BNode * SearchBList(BList phead,int x) { BNode* p=phead->last; while(p != NULL) { if(p->data==x) { return p; }
#include<stdio.h> #include<stdlib.h> #include<assert.h> typedef struct BNode { int data; struct BNode *front; struct BNode *last; }BNode,*BList;
BNode* BuyNode(int x) { BNode* p=(BNode*)malloc(sizeof(BNode)); assert(p != NULL); p->data=x; p->front=p; p->last=p; return p; } B-1); return list; } bool InsertHeadBList(BList phead,int x) { assert(phead != NULL); BNode* p=BuyNode(x); phead->last->front=p; p->last=phead->last; phead->last=p; p->front=phead; return true; }

双向链表

双向链表

第8讲 双向链表● 循环单链表的出现,虽然能够实现从任一结点出发沿着链能找到其前趋结点,但时间耗费是O (n) 。

● 如果希望从表中快速确定某一个结点的前趋,另一个解决方法就是在单链表的每个结点里再增加一个指向其前趋的指针域prior 。

这样形成的链表中就有两条方向不同的链,我们称之为双向链表。

● 双向链表的结构定义如下:typedef struct DNode{ ElemType data ;struct DNode *prior ,*next ;}DNode, * DoubleList ;● 双向链表的结点结构如图所示。

图:双链表的结点结构注:● 双向链表也是由头指针唯一确定的,● 增加头结点能使双链表的某些运算变得方便● 由于在双向链表中既有前向链又有后向链,寻找任一个结点的直接前驱结点与直接后继结点变得非常方便。

● 设指针p 指向双链表中某一结点,则有下式成立:p->prior->next = p = p->next->prior●在双向链表中,那些只涉及后继指针的算法,如求表长度、取元素、元素定位等,与单链表中相应的算法相同,● 但对于前插和删除操作则涉及到前驱和后继两个方向的指针变化,因此与单链表中的算法不同。

1、 双向链表的前插操作【算法思想】欲在双向链表第i 个结点之前插入一个的新的结点,则指针的变化情况如图所示:… p …s->prior=p->prior; ①p->prior->next=s;②s->next=p; ③p->prior=s;④【算法描述】int DlinkIns(DoubleList L,int i,ElemType e){DNode *s,*p;… /*先检查待插入的位置i是否合法(实现方法同单链表的前插操作)*/… /*若位置i合法,则找到第i个结点并让指针p指向它*/s=(DNode*)malloc(sizeof(DNode));if (s){ s->data=e;s->prior=p->prior; ①p->prior->next=s; ②s->next=p; ③p->prior=s; ④r eturn TRUE;}else return FALSE;}2、双向链表的删除操作【算法思想】欲删除双向链表中的第i个结点,则指针的变化情况如图所示:p->prior->next=p->next; ①p->next->prior=p->prior; ②free(p);【算法描述】int DlinkDel(DoubleList L,int i,ElemType *e){DNode *p;… /*先检查待插入的位置i 是否合法(实现方法同单链表的删除操作)*/… /*若位置i 合法,则找到第i 个结点并让指针p 指向它*/*e=p->data;p->prior->next=p->next; ①p->next->prior=p->prior; ②free(p);return TRUE;}3、 双向循环链表双向链表可以有循环表,称为双向循环链表。

双向链表的基本操作

双向链表的基本操作前⾯学习了如何创建⼀个,本节学习有关双向的⼀些基本操作,即如何在双向链表中添加、删除、查找或更改数据元素。

本节知识基于已熟练掌握双向链表创建过程的基础上,我们继续上节所创建的双向链表来学习本节内容,创建好的双向链表如图 1 所⽰:图 1 双向链表⽰意图双向链表添加节点根据数据添加到双向链表中的位置不同,可细分为以下 3 种情况:添加⾄表头将新数据元素添加到表头,只需要将该元素与表头元素建⽴双层逻辑关系即可。

换句话说,假设新元素节点为 temp,表头节点为 head,则需要做以下 2 步操作即可:1. temp->next=head; head->prior=temp;2. 将 head 移⾄ temp,重新指向新的表头;例如,将新元素 7 添加⾄双链表的表头,则实现过程如图 2 所⽰:图 2 添加元素⾄双向链表的表头添加⾄表的中间位置同添加数据类似,双向链表中间位置添加数据需要经过以下 2 个步骤,如图 3 所⽰:1. 新节点先与其直接后继节点建⽴双层逻辑关系;2. 新节点的直接前驱节点与之建⽴双层逻辑关系;图 3 双向链表中间位置添加数据元素添加⾄表尾与添加到表头是⼀个道理,实现过程如下(如图 4 所⽰):1. 找到双链表中最后⼀个节点;2. 让新节点与最后⼀个节点进⾏双层逻辑关系;图 4 双向链表尾部添加数据元素因此,我们可以试着编写双向链表添加数据的 C 语⾔代码,参考代码如下:1. line * insertLine(line * head,int data,int add){2. //新建数据域为data的结点3. line * temp=(line*)malloc(sizeof(line));4. temp->data=data;5. temp->prior=NULL;6. temp->next=NULL;7. //插⼊到链表头,要特殊考虑8. if (add==1) {9. temp->next=head;10. head->prior=temp;11. head=temp;12. }else{13. line * body=head;14. //找到要插⼊位置的前⼀个结点15. for (int i=1; i<add-1; i++) {16. body=body->next;17. }18. //判断条件为真,说明插⼊位置为链表尾19. if (body->next==NULL) {20. body->next=temp;21. temp->prior=body;22. }else{23. body->next->prior=temp;24. temp->next=body->next;25. body->next=temp;26. temp->prior=body;27. }28. }29. return head;30. }双向链表删除节点双链表删除结点时,只需遍历链表找到要删除的结点,然后将该节点从表中摘除即可。

数据结构之链表篇(单链表,循环链表,双向链表)C语言版

数据结构之链表篇(单链表,循环链表,双向链表)C语⾔版1.链表 链表是线性表的⼀种,由⼀系列节点(结点)组成,每个节点包含⼀个数据域和⼀个指向下⼀个节点的指针域。

链表结构可以克服数组需要预先知道数据⼤⼩的缺点,⽽且插⼊和删除元素很⽅便,但是失去数组随机读取的优点。

链表有很多种不同类型:单向链表,双向链表和循环链表。

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

2.单链表的操作 链表的操作⼀般有创建链表,插⼊节点,删除节点,遍历链表。

插⼊节点的⽅法有头插法和尾插法,头插法是在头部插⼊,尾插法是在尾部插⼊。

下⾯以⼀个带头节点,采⽤尾插法的链表说明链表的各种操作。

1 #include<stdio.h>2 #include<stdlib.h>3//单链表456//节点结构体7 typedef struct node8 {9int value;//数据域10struct node*next;//指针域11 }Node;1213 Node*createList();//创建链表并且返回头节点指针14void deleteNode(Node*head);//删除节点15void insertNode(Node*head);//插⼊节点16void travelList(Node*head);//遍历链表1718int main()19 {20 Node*head=createList();21 travelList(head);22 insertNode(head);23 travelList(head);24 deleteNode(head);25 travelList(head);26return0;27 }28//创建链表,返回头节点指针29 Node*createList()30 {31//采⽤尾插法32 Node*head;//头节点33 Node*tail;//尾节点34 Node*temp=NULL;35int 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("输⼊各个节点的值: ");4344for(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 }53return head;54 }55//遍历链表56void travelList(Node*head)57 {58while(head->next!=NULL)59 {60 printf("%d\n",head->next->value);61 head=head->next;62 }63 }64//插⼊节点65void insertNode(Node*head)66 {67int value;68int position;69int pos=0;70 Node*pre=NULL;//⽤来保存要插⼊节点的前⼀个节点71 Node*newNode;72 printf("输⼊要插⼊节点的值: ");73 scanf("%d",&value);74 printf("要插⼊的位置: ");75 scanf("%d",&position);76while(head!=NULL)77 {78 pos++;79 pre=head;80 head=head->next;81if(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//删除节点91void deleteNode(Node*head)92 {93int value;94 Node*pre=head;95 Node*current=head->next;96 printf("输⼊要删除节点的值: ");97 scanf("%d",&value);98while(current!=NULL)99 {100if(current->value==value)101 {102 pre->next=current->next;103free(current);//释放空间104break;105 }106 pre=current;107 current=current->next;108 }109 }3.循环链表 循环链表就是让尾节点的指针域不再是NULL,⽽是指向头节点从⽽形成⼀个环。

数据结构双向循环链表

题目:试编写一个在循环双向链表中进行删除操作的算法,要求删除的结点是指定结点p 的前趋结点。

主函数:#include <stdio.h>#include "List_Link.h"long InsElement(PLINKNODE_S pstSqList){int nElement;int nPosition;printf("请输入合法INT值: ");scanf("%d", &nElement);printf("请输入合法INT值作为元素在顺序表中位置: ");scanf("%d", &nPosition);if (InsertList_L(pstSqList, nPosition, nElement))//向链表中插入数据以及指定数据在链表中的位置{printf("插入操作成功\n\n");}else{printf("输入非法INT值,插入操作失败\n\n");}return 0;}long DelElement(PLINKNODE_S pstSqList){int nPosition;int nElement;printf("请输入合法INT值在顺序表中位置: ");scanf("%d", &nPosition);if (DeleteList_L(pstSqList, nPosition, &nElement))//指定数据在链表中的位置,删除该节点{printf("删除操作成功\n\n");}else{printf("输入非法INT值,删除操作失败\n\n");}return 0;}int main(){PLINKNODE_S pstLinkList;char szCommond[10];pstLinkList = (PLINKNODE_S)malloc(sizeof(LINKNODE_S));pstLinkList->nElem = 0; //通常头结点不赋值pstLinkList->pNext = pstLinkList; //将头结点的后继结点指针指向空printf("操作命令: \n");printf("i ------- 插入, d ------- 删除\n");printf("e ------- 退出, s ------- 显示当前线性表\n");printf("\n删除操作将删除指定结点的前驱结点!\n\n");while (OK){scanf("%s", &szCommond);if (szCommond[0] == 'i'){InsElement(pstLinkList);}else if (szCommond[0] == 'd'){DelElement(pstLinkList);}else if (szCommond[0] == 'e'){break;}else if (szCommond[0] == 's'){DisplayList_L(pstLinkList);}}DestoryList_L(pstLinkList);return 0;}头文件:#ifdef _cplusplusextern "C"{#endif#include <stdio.h>#include <Windows.h>#define STATUS int#define ERROR 0#define OK 1typedef struct tagLinkNode{int nElem;struct tagLinkNode *prior;struct tagLinkNode *pNext;}LINKNODE_S, *PLINKNODE_S;STATUS InsertList_L(PLINKNODE_S pstHeadNode, int nPosition, int nElement) {PLINKNODE_S p, s;int i = 0;p = pstHeadNode;while (p && i < nPosition-1){ // 寻找第nPosition-1个结点p = p->pNext;++i;}if (!p || i > nPosition-1){return ERROR; // i小于1或者大于表长}s = (PLINKNODE_S)malloc(sizeof(LINKNODE_S)); // 生成新结点s->pNext = NULL; //将结构中指针初始化为空值s->nElem = nElement;s->pNext = p->pNext; // 插入L中s->prior = p;p->pNext = s;s->pNext->prior = s; //头结点的前驱指向尾结点return OK;}STATUS DeleteList_L(PLINKNODE_S pstHeadNode, int nPosition, int *nElem){PLINKNODE_S p;int nTemp = 0;p = pstHeadNode;while (p->pNext && nTemp < nPosition - 1) //寻找第i个节点,并令p指向其前趋节点{p = p->pNext;++nTemp;}if (!(p->pNext) || (nTemp > nPosition - 1)){return ERROR; //删除位置不合理}if(!nTemp)p = p->prior; //如果输入1,则p移动到尾结点p->prior->pNext = p->pNext;p->pNext->prior = p->prior;free(p);return OK;}STATUS DisplayList_L(PLINKNODE_S pstHeadNode){PLINKNODE_S pScanNode;pScanNode = pstHeadNode;printf("HEAD <-> ");while (pScanNode->pNext != pstHeadNode){pScanNode = pScanNode->pNext;printf("%d <-> ", pScanNode->nElem);}printf("NULL\n");return OK;}STATUS DestoryList_L(PLINKNODE_S pstHeadNode) {PLINKNODE_S pScanNode, pTempNode;pScanNode = pstHeadNode;if (NULL == pstHeadNode){return ERROR;}while (pScanNode->pNext != pstHeadNode){pTempNode = pScanNode;pScanNode = pScanNode->pNext;free(pTempNode);}return OK;}#ifdef _cplusplus}#endif。

数据结构双向链表简单实现及图示

数据结构双向链表简单实现及图⽰————————————————————————————————————————————双向链表- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -和单向链表相⽐有以下优势:插⼊删除不需要移动元素外,可以原地插⼊删除可以双向遍历- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -初始化+尾插法图⽰://head始终指向头结点,p指向尾节点,⽅便后续算法使⽤删除单个图⽰:实现代码:1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 typedef struct Node pNode;5struct Node6 {7int data;8 pNode *prev, *next;9 };10/* 初始化链表,尾插法 */11 pNode *InitList(pNode **head, int n)12 {13 pNode *p, *s;14 (*head) = (pNode *)malloc(sizeof(pNode));15if ((*head) == NULL)16 exit(0);17 (*head)->next = NULL;//head的prev和next均指向NULL18 (*head)->prev = NULL;19 p = (*head);//p指向head20int i;21for (i = 0; i < n; ++i)22 {23 s = (pNode *)malloc(sizeof(pNode));24if (s == NULL)25 exit(0);26 printf("Input the value of the %dth node:", i + 1);27 scanf("%d", &s->data);28 s->next = NULL;29 p->next = s;30 s->prev = p;31 p = s;//p指向尾节点32 }33return p;34 }35/* 遍历打印 */36void PrintList(pNode *head)37 {38 pNode *p;39 p = head->next;40if (head->next == NULL)41 printf("the list is empty\n");42while(p != NULL)43 {44 printf("%d ", p->data);45 p = p->next;46 }47 printf("\n");48 }49/* 清空链表 */50void DeleteList(pNode **head)51 {52 pNode *p;53while((*head)->next != NULL)54 {55 p = (*head);56 p->next->prev = NULL;57 (*head) = p->next;58free(p);59 }60 }61/* 查找链表内的某个值 */62int SearchList(pNode *head)63 {64int number;65 printf("Values are about to be deleted:");66 scanf("%d", &number);67 pNode *p;68 p = head->next;69while(p != NULL)70 {71if (p->data == number)72 {73return number;74 }75 p = p->next;76 }77return0;78 }79/* 删除链表中某个元素,令p的前驱节点和后驱节点相互指向即可,如果p是尾节点则直接将前驱节点指向NULL*/ 80void DelNumqList(pNode **head, int n)81 {82int i;83 pNode *p;84 p = (*head)->next;85for (i = 1; i < n; ++i)86 p = p->next;87if(p->next == NULL)88 {89 p->prev->next = NULL;90free(p);91 }92else93 {94 p->next->prev = p->prev;95 p->prev->next = p->next;96free(p);97 }98 }99int main(int argc, char const *argv[])100 {101int n, element, flag;102 pNode *head, *last;103/***************************************************************/104 printf("Please input the size of the list:");105 scanf("%d", &n);106 last = InitList(&head, n);//初始化链表并赋值,返回尾节点last107 printf("%d %d \n", head->next->data, last->data); //打印为第⼀个元素和最后⼀个元素108 PrintList(head);109/***************************************************************/110 flag = SearchList(head); //搜索某个值并删除节点111if (flag > 0 && flag <= n)112 {113 DelNumqList(&head, flag);114 PrintList(head);115 }116else117 printf("Element does not exist, cannot be deleted\n");118/***************************************************************/119 DeleteList(&head);//清空列表120 PrintList(head);121return0;122 }。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档