• 线性表->链式存储->双向链表


    文字描述

      之前的链表(单链表、循环链表)的链式存储结构中只有一个指示直接后继的指针域。由此,从某个结点出发只能顺指针往后寻查其他结点。若要寻查结点的直接前驱,则需从表头指针出发。即单链表中,NextElem的执行时间为1,而PriorElem的执行时间为n。为了克服单链表这种缺点,可利用双向链表。

      在双向链表中,每个节点有两个指针域,一个指向其直接后继,一个指向其直接前驱。

    示意图

    算法分析

    插入、删除、查找、求后继等同单链表。但是求前驱不一样,其时间复杂度为1。

    代码实现

      1 //
      2 // Created by lady on 19-1-31.
      3 //
      4 
      5 #include <stdlib.h>
      6 #include <stdio.h>
      7 #include <string.h>
      8 
      9 //线性表的双向循环链表存储结构
     10 typedef struct ElemType{
     11     char data[10];
     12 }ElemType;
     13 typedef struct DuLNode{
     14     ElemType e;
     15     struct DuLNode *prior;
     16     struct DuLNode *next;
     17 }DuLNode, *DuLinkList;
     18 
     19 //构造一个空的双向循环链表
     20 static int InitList_DuL(DuLinkList *L)
     21 {
     22     (*L) = (DuLinkList)malloc(sizeof(DuLNode));
     23     (*L)->prior = (*L);
     24     (*L)->next = (*L);
     25     memset((*L)->e.data, 0, sizeof((*L)->e.data));
     26     return 0;
     27 }
     28 
     29 //销毁L
     30 static int Destory_DuL(DuLinkList *L)
     31 {
     32     DuLNode *p = NULL;
     33     DuLNode *q = NULL;
     34     p = (*L)->next;
     35     while(p){
     36         q = p;
     37         p = p->next;
     38         free(q);
     39         if(p == (*L))
     40             break;
     41     }
     42     free(*L);
     43     (*L) = NULL;
     44     return 0;
     45 }
     46 
     47 //返回双向链表L中的第i个位置的元素
     48 static DuLNode *GetElemP_DuL(DuLinkList *L, int i)
     49 {
     50     if(L == NULL){
     51         return NULL;
     52     }
     53     DuLNode *p = (*L)->next;
     54     int index = 1;
     55     while(index<i && p){
     56         index += 1;
     57         p = p->next;
     58     }
     59     if(index == i && p){
     60         return p;
     61     }else{
     62         return NULL;
     63     }
     64 }
     65 
     66 //在L的指定位置i的元素前面插入元素e
     67 static int ListInsert_DuL(DuLinkList *L, int i, ElemType e)
     68 {
     69     DuLNode *p = NULL;
     70     DuLNode *new = NULL;
     71     if((p=GetElemP_DuL(L, i)) == NULL){
     72         return -1;
     73     }
     74     if((new = (DuLNode*)malloc(sizeof(DuLNode))) == NULL){
     75         return -1;
     76     }
     77     new->e = e;
     78     new->prior = p->prior;
     79     p->prior->next = new;
     80     new->next = p;
     81     p->prior = new;
     82     return 0;
     83 }
     84 
     85 //删除L中的第loc个数据元素,并将被删元素的值存放在e中
     86 static int ListDelete_DuL(DuLinkList *L, int i, ElemType *e)
     87 {
     88     DuLNode *p = NULL;
     89     if((p=GetElemP_DuL(L, i)) == NULL){
     90         return -1;
     91     }
     92     (*e) = p->e;
     93     p->prior->next = p->next;
     94     p->next->prior = p->prior;
     95     free(p);
     96     return 0;
     97 }
     98 
     99 //依次对L的每个数据元素调用函数fun
    100 static int listTraverse_DuL(DuLinkList *L, int (*fun)(ElemType,int), char note[])
    101 {
    102     printf("遍历双向循环链表%s:", note);
    103     DuLNode *p = NULL;
    104     p = (*L)->next;
    105     int i = 1;
    106     while(p){
    107         fun(p->e, i);
    108         i+=1;
    109         p = p->next;
    110         if(p == (*L))
    111             break;
    112     }
    113     printf("
    ");
    114     return 0;
    115 }
    116 
    117 static int print(ElemType e, int loc)
    118 {
    119     printf("%3d=%-10s", loc, e.data);
    120 }
    121 
    122 //创建一个长度为n的双向链表
    123 static int CreateList_DuL(DuLinkList *L, int n, char note[])
    124 {
    125     printf("创建一个长度为%d的双向循环链表%s!
    ", n, note);
    126     InitList_DuL(L);
    127     ElemType e;
    128     int i = 0;
    129     for(i=0; i<n; i++){
    130         printf("输入第%d个元素:", i+1);
    131         scanf("%s[^\n]", e.data);
    132         ListInsert_DuL(L, i+1, e);
    133     }
    134     return 0;
    135 }
    136 
    137 int main(int argc, char *argv[])
    138 {
    139     ElemType e;
    140     DuLinkList L;
    141     int location=0;
    142 
    143     CreateList_DuL(&L, 5, "L");
    144 
    145     listTraverse_DuL(&L, print, "L");
    146 
    147 
    148     printf("输入插入元素的位置:");
    149     scanf("%d", &location);
    150     printf("输入插入元素的数据:");
    151     scanf("%s[^\n]", e.data);
    152     ListInsert_DuL(&L, location, e);
    153     listTraverse_DuL(&L, print, "L");
    154 
    155     printf("输入删除元素的位置:");
    156     scanf("%d", &location);
    157     ListDelete_DuL(&L, location, &e);
    158 
    159     printf("位于%d的元素%s已经从双向循环链表中被删除!
    ", location, e.data);
    160     listTraverse_DuL(&L, print, "L");
    161 
    162     Destory_DuL(&L);
    163     printf("双向链表已经被销毁!
    ");
    164     return 0;
    165 }
    双向链表

    代码运行

    /home/lady/CLionProjects/untitled/cmake-build-debug/untitled
    创建一个长度为5的双向循环链表L!
    输入第1个元素:c
    输入第2个元素:b
    输入第3个元素:e
    输入第4个元素:g
    输入第5个元素:f
    遍历双向循环链表L:  1=c           2=b           3=e           4=g           5=f         
    输入插入元素的位置:3
    输入插入元素的数据:test
    遍历双向循环链表L:  1=c           2=b           3=test        4=e           5=g           6=f         
    输入删除元素的位置:4
    位于4的元素e已经从双向循环链表中被删除!
    遍历双向循环链表L:  1=c           2=b           3=test        4=g           5=f         
    双向链表已经被销毁!
    
    Process finished with exit code 0
  • 相关阅读:
    Windows抓取密码总结
    PHP一句话简单免杀
    Shiro反序列化利用
    windows绕过杀软添加账户密码
    java基础-操作符
    微信小程序开发笔记(十一)--输入框计数
    微信小程序开发笔记(十)--多选标签效果
    微信小程序开发笔记(九)--单选标签效果
    微信小程序开发笔记(八)--路由跳转
    proxy_pass 代理转发
  • 原文地址:https://www.cnblogs.com/aimmiao/p/10392258.html
Copyright © 2020-2023  润新知