数据结构之双链表

来源:互联网 发布:php分销源码 编辑:程序博客网 时间:2024/06/06 03:39

        在单链表中,由于每个结点只包含有一个指向后继结点的指针,所以当访问过一个结点后,只能接着访问它的后继结点,而无法访问它的前驱结点。

        另一种可以采用的方法是:在每个结点中除包含有数值域外,设置有两个指针域,分别用以指向其前驱结点和后继结点,这样构成的链接表称之为线性双向链接表,简称双链表。 

   在单链表中,进行结点插入和删除时涉及到前后结点的一个指针域的变化。而在双链表中,结点的插入和删除操作涉及到前后结点的两个指针域的变化。

 

归纳起来,在双链表中p所指的结点之后插入一个*s结点。其操作语句描述为:
       

   s->next=p->next;/*将*s插入到*p之后*/   p->next->prior=s;   s->prior=p;   p->next=s;


 

归纳起来,删除双链表L中*p结点的后续结点。其操作语句描述为:
      

p->next=p->next->next;q->next->prior=p;
完整代码如下:
<pre name="code" class="cpp">//双链表。#include "stdafx.h"#include <stdio.h>#include <malloc.h>#include <stdlib.h>//需要使用exit函数typedef char ElemType;//注意有分号//定义双链表typedef struct DNode{ElemType data;struct DNode *prior;//指向前驱节点struct DNode *next;//指向后继节点}DLinkList, *pList;//初始化void InitList(pList &L){L = (pList)malloc(sizeof(DLinkList));//创建头节点if (NULL == L){   exit(0);//分配失败则返回}L->prior = L->next = NULL;}//销毁双链表void DestroyList(pList &L){pList p = L;pList q = p->next;while (q != NULL){   free(p);//释放当前节点   p = q;//把下一个节点变为当前节点   q = p->next;//取下一个节点}free(p);//释放最后一个节点p = NULL;//防止p成为野指针}bool ListEmpty(DLinkList *L)//判线性表是否为空表{return(L->next==NULL);}//取得双链表的长度int ListLength(pList L){pList p = L;    int i = 0;//一定要初始化,否则i++是未定义的while (p->next != NULL){   i++;   p = p->next;}return i;}//输出双链表,声明为const表明在这是只读的,出于安全的考虑void DispList(const pList L){pList p = L->next;//p指向第一个节点while (p != NULL){printf("%c", p->data);p = p->next;}printf("\n");}//获取双链表中某个元素bool GetElem(pList L,int i, ElemType &e){int j = 0;pList p = L;//找到i位置的节点while (j < i && p != NULL ){    j++;p = p->next;}if (NULL == p){    return false;//没有找到}else{e = p->data;return true;}}//查找元素的位置int LocateElem(pList L, ElemType e){int n = 1;//返回逻辑位置,如果要返回索引位置则是0pList p = L->next;//p指向第一个节点//查找元素while (p != NULL && p->data != e){         n++; p = p->next;}if (NULL == p){      return 0;//表示没有这个元素}else{  return n;}}//插入元素bool ListInsert(pList L, int i, ElemType e){int j = 0;pList p = L;pList s;//找到i-1个节点while (j < i - 1 && p != NULL){   j++;   p = p->next;}if (NULL == p){return false;//未找到i-1个节点}else{    s = (pList)malloc(sizeof(DLinkList));//创建新节点if(NULL == s){   exit(0);}s->data = e;//将*s插入*p后s->next = p->next;//s代替p指向下一个节点if (p->next != NULL){p->next->prior = s;//s代替p成为后一个节点的前驱}s->prior = p;//p成为s的前驱p->next = s;//s成为p的后继return true;}}//删除元素bool ListDelete(pList &L, int i, ElemType &e){int j = 0;pList p = L;pList q;//查找第i-1个节点while (j < i - 1 && p != NULL){    j++;p = p->next;}if (NULL == p){    return false;//未找到第i-1个节点}else{q = p->next;//q指向i节点,既要删除的节点    if (NULL == q){   return false;//不存在第i个节点}e = q->data;p->next = q->next;//删除*q节点,p->next = p->next->nextif (p->next != NULL){//注意此时p->next = p->next->nextp->next->prior = p;}free(q);q = NULL;return true;}}//双链表排序void Sort(pList &head){pList p = head->next;//指向第一个节点pList q, r;//要有一个或一个以上节点if (p != NULL){r = p->next;//r保存*p结点后继结点的指针p->next = NULL;//构造只含一个数据结点的有序表p = r;//此时p=head->next->next//实现升序排列while (p != NULL){  r = p->next;//r保存*p结点后继结点的指针  q = head;  while(q->next != NULL && q->next->data < p->data)  {  //取下一个节点  q = q->next;  }  p->next = q->next;  //将*p插入到*q之后  if (q->next != NULL)  {  q->next->prior = p;  }  q->next = p;  p->prior = q;  p = r;    }}}void main(){DLinkList *h;ElemType e;printf("双链表的基本运算如下:\n");printf("  (1)初始化双链表h\n");InitList(h);printf("  (2)依次采用尾插法插入a,b,c,d,e元素\n");ListInsert(h,1,'a');ListInsert(h,2,'b');ListInsert(h,3,'c');ListInsert(h,4,'d');ListInsert(h,5,'e');printf("  (3)输出双链表h:");DispList(h);printf("  (4)双链表h长度=%d\n",ListLength(h));printf("  (5)双链表h为%s\n",(ListEmpty(h)?"空":"非空"));GetElem(h,3,e);printf("  (6)双链表h的第3个元素=%c\n",e);printf("  (7)元素a的位置=%d\n",LocateElem(h,'a'));printf("  (8)在第4个元素位置上插入f元素\n");ListInsert(h,4,'f');printf("  (9)输出双链表h:");DispList(h);printf("  (10)删除h的第3个元素\n");ListDelete(h,3,e);printf("  (11)输出双链表h:");DispList(h);printf("  (12)排序:");Sort(h);DispList(h);printf("  (13)释放双链表h\n");DestroyList(h);}


                                             
0 0
原创粉丝点击