• 数据结构 双向链表 C语言实现


     

    dlist.h

     1 #ifndef __dList_H
     2 #define __dlist_H
     3 
     4 typedef    int Item;
     5 typedef struct Node *PNode;
     6 typedef PNode Position;
     7 /*定义节点类型*/
     8 typedef struct Node
     9 {
    10     Item data; /*数据域*/
    11     PNode previous; /*指向前驱*/
    12     PNode next;    /*指向后继*/
    13 }Node;
    14 
    15 /*定义链表类型*/
    16 typedef struct
    17 {
    18     PNode head; /*指向头节点*/
    19     PNode tail; /*指向尾节点*/
    20     int size;
    21 }DList;
    22 
    23 
    24 /*分配值为i的节点,并返回节点地址*/
    25 Position MakeNode(Item i);
    26 /*释放p所指的节点*/
    27 void FreeNode(PNode p);
    28 /*构造一个空的双向链表*/
    29 DList* InitList();
    30 /*摧毁一个双向链表*/
    31 void DestroyList(DList *plist);
    32 /*将一个链表置为空表,释放原链表节点空间*/
    33 void ClearList(DList *plist);
    34 /*返回头节点地址*/
    35 Position GetHead(DList *plist);
    36 /*返回尾节点地址*/
    37 Position GetTail(DList *plist);
    38 /*返回链表大小*/
    39 int GetSize(DList *plist);
    40 /*返回p的直接后继位置*/
    41 Position GetNext(Position p);
    42 /*返回p的直接前驱位置*/
    43 Position GetPrevious(Position p);
    44 /*将pnode所指节点插入第一个节点之前*/
    45 PNode InsFirst(DList *plist,PNode pnode);
    46 /*将链表第一个节点删除并返回其地址*/
    47 PNode DelFirst(DList *plist);
    48 /*获得节点的数据项*/
    49 Item GetItem(Position p);
    50 /*设置节点的数据项*/
    51 void SetItem(Position p,Item i);
    52 /*删除链表中的尾节点并返回其地址,改变链表的尾指针指向新的尾节点*/
    53 PNode Remove(DList *plist);
    54 /*在链表中p位置之前插入新节点S*/
    55 PNode InsBefore(DList *plist,Position p,PNode s);
    56 /*在链表中p位置之后插入新节点s*/
    57 PNode InsAfter(DList *plist,Position p,PNode s);
    58 /*返回在链表中第i个节点的位置*/
    59 PNode LocatePos(DList *plist,int i);
    60 /*依次对链表中每个元素调用函数visit()*/
    61 void ListTraverse(DList *plist,void (*visit)());
    62 
    63 #endif

    dlist.c

      1 #include"dlist.h"
      2 #include<malloc.h>
      3 #include<stdlib.h>
      4 /*分配值为i的节点,并返回节点地址*/
      5 Position MakeNode(Item i)
      6 {
      7     PNode p = NULL;
      8     p = (PNode)malloc(sizeof(Node));
      9     if(p!=NULL)
     10     {
     11         p->data = i;
     12         p->previous = NULL;
     13         p->next = NULL;
     14     }
     15     return p;
     16 }
     17 /*释放p所指的节点*/
     18 void FreeNode(PNode p)
     19 {
     20      free(p);
     21 }
     22 /*构造一个空的双向链表*/
     23 DList * InitList()
     24 {
     25     DList *plist = (DList *)malloc(sizeof(DList));
     26     PNode head = MakeNode(0);
     27     if(plist!=NULL)
     28     {
     29         if(head!=NULL)
     30         {
     31             plist->head = head;
     32             plist->tail = head;
     33             plist->size = 0;
     34         }
     35         else
     36             return NULL;
     37     }
     38     return plist;
     39 }
     40 
     41 /*摧毁一个双向链表*/
     42 void DestroyList(DList *plist)
     43 {
     44     ClearList(plist);
     45     free(GetHead(plist));
     46     free(plist);
     47 }
     48 
     49 /*判断链表是否为空表*/
     50 int IsEmpty(DList *plist)
     51 {
     52     if(GetSize(plist) == 0 && GetTail(plist) == GetHead(plist))
     53         return 1;
     54     else
     55         return 0;
     56 }
     57 /*将一个链表置为空表,释放原链表节点空间*/
     58 void ClearList(DList *plist)
     59 {
     60     PNode temp,p;
     61     p = GetTail(plist);
     62     while(!IsEmpty(plist))
     63     {
     64         temp = GetPrevious(p);
     65         FreeNode(p);
     66         p = temp;
     67         plist->tail = temp;
     68         plist->size--;
     69     }
     70 }
     71 
     72 /*返回头节点地址*/
     73 Position GetHead(DList *plist)
     74 {
     75     return plist->head;
     76 }
     77 
     78 /*返回尾节点地址*/
     79 Position GetTail(DList *plist)
     80 {
     81     return plist->tail;
     82 }
     83 
     84 /*返回链表大小*/
     85 int GetSize(DList *plist)
     86 {
     87     return plist->size;
     88 }
     89 
     90 /*返回p的直接后继位置*/
     91 Position GetNext(Position p)
     92 {
     93     return p->next;
     94 }
     95 
     96 /*返回p的直接前驱位置*/
     97 Position GetPrevious(Position p)
     98 {
     99     return p->previous;
    100 }
    101 
    102 /*将pnode所指节点插入第一个节点之前*/
    103 PNode InsFirst(DList *plist,PNode pnode)
    104 {
    105     Position head = GetHead(plist);
    106 
    107     if(IsEmpty(plist))
    108         plist->tail = pnode;
    109     plist->size++;
    110 
    111     pnode->next = head->next;
    112     pnode->previous = head;
    113 
    114     if(head->next!=NULL)
    115         head->next->previous = pnode;
    116     head->next = pnode;
    117 
    118     return pnode;
    119 }
    120 
    121 /*将链表第一个节点删除,返回该节点的地址*/
    122 PNode DelFirst(DList *plist)
    123 {
    124     Position head = GetHead(plist);
    125     Position p=head->next;
    126     if(p!=NULL)
    127     {
    128         if(p==GetTail(plist))
    129             plist->tail = p->previous;
    130         head->next = p->next;
    131         head->next->previous = head;
    132         plist->size--;
    133 
    134     }
    135     return p;
    136 }
    137 
    138 /*获得节点的数据项*/
    139 Item GetItem(Position p)
    140 {
    141     return p->data;
    142 }
    143 
    144 /*设置节点的数据项*/
    145 void SetItem(Position p,Item i)
    146 {
    147     p->data = i;
    148 }
    149 
    150 /*删除链表中的尾节点并返回地址,改变链表的尾指针指向新的尾节点*/
    151 PNode Remove(DList *plist)
    152 {
    153     Position p=NULL;
    154     if(IsEmpty(plist))
    155         return NULL;
    156     else
    157     {
    158         p = GetTail(plist);
    159         p->previous->next = p->next;
    160         plist->tail = p->previous;
    161         plist->size--;
    162         return p;
    163     }
    164 }
    165 /*在链表中p位置之前插入新节点s*/
    166 PNode InsBefore(DList *plist,Position p,PNode s)
    167 {
    168     s->previous = p->previous;
    169     s->next = p;
    170     p->previous->next = s;
    171     p->previous = s;
    172 
    173     plist->size++;
    174     return s;
    175 }
    176 /*在链表中p位置之后插入新节点s*/
    177 PNode InsAfter(DList *plist,Position p,PNode s)
    178 {
    179     s->next = p->next;
    180     s->previous = p;
    181 
    182     if(p->next != NULL)
    183         p->next->previous = s;
    184     p->next = s;
    185 
    186     if(p == GetTail(plist))
    187         plist->tail = s;
    188 
    189     plist->size++;
    190     return s;
    191 }
    192 
    193 /*返回在链表中第i个节点的位置*/
    194 PNode LocatePos(DList *plist,int i)
    195 {
    196     int cnt = 0;
    197     Position p = GetHead(plist);
    198     if(i>GetSize(plist)||i<1)
    199         return NULL;
    200 
    201     while(++cnt<=i)
    202     {
    203         p=p->next;
    204     }
    205 
    206     return p;
    207 }
    208 
    209 /*依次对链表中每个元素调用函数visit()*/
    210 void ListTraverse(DList *plist,void (*visit)())
    211 {
    212     Position p = GetHead(plist);
    213     if(IsEmpty(plist))
    214         exit(0);
    215     else
    216     {
    217 
    218         while(p->next!=NULL)
    219         {
    220             p = p->next;
    221             visit(p->data);
    222         }
    223     }
    224 }

    test.c

     1 #include"dlist.h"
     2 #include<stdio.h>
     3 
     4 void print(Item i)
     5 {
     6     printf("数据项为%d 
    ",i);
     7 }
     8 int main()
     9 {
    10     DList *plist = NULL;
    11     PNode p = NULL;
    12 
    13     plist = InitList();
    14     p = InsFirst(plist,MakeNode(1));
    15     InsBefore(plist,p,MakeNode(2));
    16     InsAfter(plist,p,MakeNode(3));
    17 
    18     printf("p前驱位置的值为%d
    ",GetItem(GetPrevious(p)));
    19     printf("p位置的值为%d
    ",GetItem(p));
    20     printf("p后继位置的值为%d
    ",GetItem(GetNext(p)));
    21 
    22 
    23     printf("遍历输出各节点数据项:
    ");
    24     ListTraverse(plist,print);
    25     printf("除了头节点该链表共有%d个节点
    ",GetSize(plist));
    26     FreeNode(DelFirst(plist));
    27     printf("删除第一个节点后重新遍历输出为:
    ");
    28     ListTraverse(plist,print);
    29     printf("除了头节点该链表共有%d个节点
    ",GetSize(plist));
    30     DestroyList(plist);
    31     printf("链表已被销毁
    ");
    32 }

    运行结果:

    [walt740@localhost 02.Doublylinklist]$ gcc test.c dlist.c dlist.h -o test
    [walt740@localhost 02.Doublylinklist]$ tree -L 2
    .
    ├── dlist.c
    ├── dlist.h
    ├── test
    ├── test.c
    └── 345217214345220221351223276350241250
        ├── bin
        ├── obj
        ├── 345217214345220221351223276350241250.cbp
        ├── 345217214345220221351223276350241250.depend
        └── 345217214345220221351223276350241250.layout
    
    3 directories, 7 files
    [walt740@localhost 02.Doublylinklist]$ ./test
    p前驱位置的值为2
    p位置的值为1
    p后继位置的值为3
    遍历输出各节点数据项:
    数据项为2 
    数据项为1 
    数据项为3 
    除了头节点该链表共有3个节点
    删除第一个节点后重新遍历输出为:
    数据项为1 
    数据项为3 
    除了头节点该链表共有2个节点
    链表已被销毁
    [walt740@localhost 02.Doublylinklist]$ ^

     转自 -- http://blog.csdn.net/hopeyouknow/article/details/6716177

  • 相关阅读:
    docker 安装 clickhouse单机版
    CockRoachDB简介
    Ubuntu18.04 LTS Cockroach集群搭建
    ClickHouse 的一些优化参数
    ClickHouse 概念整理
    OOM Killer机制
    win10系统下载地址
    Quartz.Net在C#中的使用
    JavaScript的undefined与null、NaN的区别
    Java Web基础回顾 —JSP
  • 原文地址:https://www.cnblogs.com/BinBinStory/p/7119278.html
Copyright © 2020-2023  润新知