什么是双向链表
双向链表同单链表一样,都属于链表。但双向链表属于复杂型的链表,在双向链表中,每一个节点都存在前驱,后继和数据。而双向链表的出现则是为了解决算法频繁的寻找前驱节点,如果就单链表来说,每次寻找前驱节点都要重新遍历一遍链表的话,会影响真个程序的执行效率,增加了算法的时间复杂度。双链表的前驱就完美的解决了这个问题。
双向链表的定义
双链表的节点定义主要包括前驱和后继还有指针域,如图所示:
而节点的结构定义为:
typedef struct line{
ElemType data;
struct line *pre;//指向前驱节点
struct line *next;//指向后继节点
}Line,*LinkList;
双向链表的尾插法
双向链表的尾插法和单链表的尾插法实现感觉差别不大,也就多了一个前驱节点,但总的来说代码的核心部分还是同样的实现。
LinkList DoubleLinkList_T(){
Line *line,*L;
line=(Line*) malloc(sizeof (Line));
line->pre=NULL;
line->next=NULL;
L=line;
int x;
while (scanf("%d",&x)!=EOF){
Line *node;
node= (Line*)malloc(sizeof(Line));
node->data=x;
node->next=L->next;
L->next= node;
node->pre=L;
L=node;//往后移一步
}
return line;
}
双向链表的插入
双向链表在插入数据的过程,如图所示:
status DoubleLinkList_Insert(LinkList L,int i,ElemType e){
Line *Node,*p,*r;
Node=L;
int j=1;
while (j<i){
Node=Node->next;
j++;
}
p=Node->next;//L的后进
r=(Line*) malloc(sizeof(Line));
if(r==NULL){
printf("分配内存失败");
return ERROR;
}
r->data=e;
r->next=Node->next;
Node->next=r;
r->pre=p->pre;
p->pre=r;
return OK;
}
对于插入操作最核心的的也就是为下面这4步:
r->next=Node->next;//新节点指向
Node->next=r;
r->pre=p->pre;
p->pre=r;//向前
第一步就是先连接上要成为后继的节点。过后就修改原来节点的后继指向,让其指向新创建的节点,这也就是第二步。这2步完成之后第三步也就需要修改后继的pre了,只有这样才能连上。最后也要将新创立的节点的pre连接上之前的节点,也就是第4个步骤。
双向链表的删除
双向链表的删除,就是要直接遍历整个链表得到删除节点的位置,再通过其前驱和后继完成对指针的删除操作。
status DoubleLinkList_Delete(LinkList L,ElemType e){
Line *Node,*p,*r;
Node=L;
//通过传入得到数据进行对比找到对应的节点
while (Node->data!=e){
Node=Node->next;
}
//通过修改其前驱和后继让需要删除的节点脱离
p=Node->next;
r=Node->pre;
p->pre=Node->pre;
r->next=Node->next;
//释放目标节点
free(Node);
return OK;
}
完整代码
#include "stdlib.h"
#include "stdio.h"
#define OK 1
#define ERROR 0
typedef int status;
typedef int ElemType;
typedef struct line{
ElemType data;
struct line *pre;
struct line *next;
}Line,*LinkList;
LinkList DoubleLinkList_T(){
Line* line,*L;
line=(Line*) malloc(sizeof (Line));
line->pre=NULL;
line->next=NULL;
L=line;
int x;
while (scanf("%d",&x)!=EOF){
Line *node;
node= (Line*)malloc(sizeof(Line));
node->data=x;
node->next=L->next;
L->next= node;
node->pre=L;
L=node;
}
return line;
}
void PrintList(LinkList list){
list=list->next;
while ( list){
printf("%d ",list->data);
list=list->next;
}
}
status DoubleLinkList_Insert(LinkList L,int i,ElemType e){
Line *Node,*p,*r;
Node=L;
int j=1;
while (j<i){
Node=Node->next;
j++;
}
p=Node->next;//L的后进
r=(Line*) malloc(sizeof(Line));
if(r==NULL){
printf("分配内存失败");
return ERROR;
}
r->data=e;
r->next=Node->next;
Node->next=r;
r->pre=p->pre;
p->pre=r;
return OK;
}
status DoubleLinkList_Delete(LinkList L,ElemType e){
Line *Node,*p,*r;
Node=L;
while (Node->data!=e){
Node=Node->next;
}
p=Node->next;
r=Node->pre;
p->pre=Node->pre;
r->next=Node->next;
free(Node);
return OK;
}
int main(){
Line *line=DoubleLinkList_T();
printf("初始的链表:");
PrintList(line);
printf("\n");
DoubleLinkList_Insert(line,3,7);
printf("插入的链表:");
PrintList(line);
DoubleLinkList_Delete(line,3);
printf("\n");
printf("删除后的链表:");
PrintList(line);
}