引言:
单链表存在一个问题,当我们想要訪问某个结点的前一个结点时。要从头结点開始訪问。显然这种操作是令人烦躁的。为此,双向链表出现,它比单链表多出了一个指针域。指向前一个结点。
这样,对于双向链表。就能够方便的从后向前遍历链表了。但多出的问题是对于插入和删除结点的开销要添加一倍。
分析描写叙述:
双向链表存储结构图为:,用结构体表演示样例如以下:
typedef int ElemType; typedef struct LNode{ ElemType data; struct LNode *prior; struct LNode *next; }LNode, *PLNode;
双向链表的初始化。双向链表的初始化,即分配一个LNode结构体大小的内存。使它的prior指针和next指针都指向结点本身。
PLNode InitDList(void) { PLNode HeadLNode = (PLNode)malloc(sizeof(LNode)); if(HeadLNode == NULL){ printf("malloc memory fail. "); return NULL; } HeadLNode->prior = HeadLNode->next = HeadLNode; return HeadLNode; }
双向链表创建链表。向已经初始化的双向链表的头部插入结点元素。
PLNode CreateDList(PLNode PHeadNode) { PLNode TmpLNode = (PLNode)malloc(sizeof(LNode)); if(TmpLNode == NULL){ printf("malloc memory fail. "); return PHeadNode; } TmpLNode->next = NULL; while(scanf("%d", &TmpLNode->data) != 0){ TmpLNode->next = PHeadNode->next; TmpLNode->prior = PHeadNode; PHeadNode->next = TmpLNode; if(TmpLNode->next != NULL)//此处的推断是针对空链表的操作,假设是空链表,以下的语句就不做。 TmpLNode->next->prior = TmpLNode; TmpLNode = (PLNode)malloc(sizeof(LNode)); if(TmpLNode == NULL){ return PHeadNode; } } free(TmpLNode); return PHeadNode; }
双向链表的遍历。此处的链表的遍历与前面提到的单链表的遍历没有什么不同。须要注意的地方还是对參数的保护。
void TraverseDList(PLNode PHeadNode) { PLNode TmpLNode = PHeadNode; if(PHeadNode == NULL) { printf("input element faulse. "); return ; } while(TmpLNode->next != NULL){ printf("%d ", TmpLNode->next->data); TmpLNode = TmpLNode->next; } putchar(' '); }
双向链表的长度。跟求单链表长度一样。
int ListLength(PLNode PHeadNode) { int count = 0; while(PHeadNode->next != NULL){ count++; PHeadNode = PHeadNode->next; } return count; }
双向链表中插入节点元素。给定一个双向链表和插入位置,给定一个结点元素,向给定的链表中插入该结点。
PLNode InsertDList(PLNode PHeadNode, ElemType data, int Index) { int index = 0; PLNode TmpLNode = PHeadNode; if(PHeadNode == NULL || Index < 0 || Index > ListLength(PHeadNode) + 1){ printf("input element faulse. "); return NULL; } for(index = 1; index < Index; index++){ TmpLNode = TmpLNode->next; } PLNode Tmp = (PLNode)malloc(sizeof(LNode)); if(Tmp == NULL){ printf("malloc memory faluse. "); return PHeadNode; } Tmp->data = data; Tmp->next = TmpLNode->next; Tmp->prior = TmpLNode->prior; TmpLNode->next = Tmp; TmpLNode->prior = Tmp; return PHeadNode; }
双向链表中删除结点。
PLNode DeleteList(PLNode PHeadNode, int Index) { int index; PLNode TmpNode = PHeadNode; if(PHeadNode == NULL || Index < 0 || Index > ListLength(PHeadNode)){ printf("input element faulse. "); return NULL; } for(index = 0; index < Index; index++){ TmpNode = TmpNode->next; } TmpNode->prior->next = TmpNode->next; if(TmpNode->next != NULL) TmpNode->next->prior = TmpNode->prior; free(TmpNode); return PHeadNode; }
双向链表中删除结点。
PLNode DeleteList(PLNode PHeadNode, int Index) { int index; PLNode TmpNode = PHeadNode; if(PHeadNode == NULL || Index <= 0 || Index > ListLength(PHeadNode)){ printf("input element faulse. "); return NULL; } for(index = 0; index < Index; index++){ TmpNode = TmpNode->next; } TmpNode->prior->next = TmpNode->next; TmpNode->next->prior = TmpNode->prior; free(TmpNode); return PHeadNode; }