zoukankan      html  css  js  c++  java
  • 线性表的链式存储结构(C语言实现)

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 
      4 #define OK 1
      5 #define ERR 2
      6 #define TRUE 1
      7 #define FALSE 0
      8 
      9 typedef int status; //定义函数返回的状态,OK & ERR
     10 typedef char datatype; //定义线性表中每个结点的数据类型,这里暂定为字符型
     11 
     12 typedef struct LinkList_anon{
     13     datatype data; //数据区
     14     struct LinkList_anon * next; //指针区
     15 } LinkList;
     16 
     17 /* 函数原型,线性表的基本操作 */
     18 LinkList *createLinkList(datatype first_node_value);
     19 status isEmpty(LinkList *L);
     20 void clear(LinkList **L);
     21 int getLength(LinkList *L);
     22 int locateNode(LinkList *L,datatype node_to_locate);
     23 datatype getNode(LinkList *L, int index);
     24 status insert(LinkList **L, int index, datatype node_to_insert);
     25 status delete(LinkList **L, int index);
     26 void showList(LinkList *L);
     27 
     28 int main(){
     29     /* 测试 */
     30     LinkList *root; //指向线性表
     31     root=createLinkList('A'); //创建一个线性表
     32     printf("Length = %d
    ",getLength(root)); //打印线性表的当前长度
     33     printf("isEmpty = %d
    ",isEmpty(root)); //打印线性表是否为空
     34     insert(&root,0,'B'); //头插法插入2个结点
     35     insert(&root,0,'C');
     36     printf("Length = %d
    ",getLength(root));
     37     printf("isEmpty = %d
    ",isEmpty(root));
     38     showList(root);
     39     putchar('
    ');
     40     insert(&root,getLength(root),'D'); //尾插法插入2个结点
     41     insert(&root,getLength(root),'E'); //尾插法插入2个结点
     42     printf("Length = %d
    ",getLength(root));
     43     printf("isEmpty = %d
    ",isEmpty(root));
     44     showList(root);
     45     putchar('
    ');
     46     insert(&root,1,'F'); //在index=1(第2个结点)插入新结点
     47     insert(&root,2,'G'); //在index=2(第3个结点)插入新节点
     48     insert(&root,2,'H'); //在index=2(第3个结点)插入新节点
     49     printf("Length = %d
    ",getLength(root));
     50     printf("isEmpty = %d
    ",isEmpty(root));
     51     showList(root); //打印线性表
     52     putchar('
    ');
     53     delete(&root,0); //删除头结点
     54     showList(root);
     55     putchar('
    ');
     56     delete(&root,getLength(root)-1); //删除尾结点
     57     showList(root);
     58     putchar('
    ');
     59     delete(&root,3); //删除index=3(第4个)结点
     60     showList(root);
     61     putchar('
    ');
     62     printf("Locate = %d
    ",locateNode(root,'A')); //打印查找到的结点的位置
     63     printf("getNode = %c
    ",getNode(root,1)); //打印下标是1的结点的值
     64     clear(&root); //清空线性表
     65     printf("isEmpty = %d",isEmpty(root));
     66 
     67     return 0;
     68 }
     69 
     70 LinkList *createLinkList(datatype first_node_value){
     71     LinkList *tmp;
     72     tmp=malloc(sizeof(LinkList));//void*类型指针能自动转为其他类型的指针
     73     tmp->data=first_node_value; //初始化头指针的数据区
     74     tmp->next=NULL; //初始化头结点的指针区
     75     return tmp;
     76 }
     77 status isEmpty(LinkList *L){
     78     if (L==NULL)
     79         return TRUE; //链表为空返回TRUE
     80     else
     81         return FALSE; //链表不为空返回FALSE
     82 }
     83 void clear(LinkList **L){
     84     if (isEmpty(*L)==FALSE){
     85         //不为空时才执行删除
     86         LinkList * p,* q; //p始终指向当前要被删除的结点,而q始终指向要被删除的结点的下一个
     87         p=*L; //将p指向线性表的头结点
     88         while (p!=NULL){
     89             //p不是NULL就继续循环
     90             q=p->next; //q始终指向下一个结点
     91             free(p); //释放p所指的结点
     92             p=q; //交换
     93         }
     94         *L=NULL; //将指向线性表的指针设为NULL
     95     }
     96 }
     97 int getLength(LinkList *L){
     98     int i=0;
     99     LinkList * p=L;
    100     if (isEmpty(L)==TRUE) return 0;
    101     while (p){
    102         i++;
    103         p=p->next;
    104     }
    105     return i;
    106 }
    107 int locateNode(LinkList *L, datatype node_to_locate){
    108     //返回找到的结点的index
    109     //node_to_locate应当是能唯一标识一个结点的数据,否则只返回匹配的第一个结点
    110     int i;
    111     int total=getLength(L);
    112     LinkList * p=L;
    113     for (i=0; i<total; i++){
    114         if (p->data==node_to_locate)
    115             return i;
    116         else
    117             p=p->next;
    118     }
    119     return -1; //未找到任何匹配
    120 }
    121 datatype getNode(LinkList *L, int index){
    122     //index表示线性表中第N个结点,头结点的index是0
    123     int i=0; //计数器
    124     LinkList * p=L; //临时结点,用于遍历
    125     if (isEmpty(L)==TRUE) return (datatype)ERR; //线性表为空
    126     while (p!=NULL && i<index){
    127         //p不是NULL且i还没等于index时,循环继续
    128         p=p->next;
    129         i++;
    130     }
    131     return p->data;
    132 }
    133 status insert(LinkList **L, int index, datatype node_to_insert){
    134     //node_to_insert表示想要插入的结点
    135     //当列表为空时,只有index=0才能插入
    136     //当index=0时,即头插,会修改传入的指针,将其指向新的头结点
    137     //当index=getLength(root)时,即尾插
    138     int k;
    139     LinkList * p;
    140     LinkList * tmp=malloc(sizeof(LinkList));
    141     if (index<0) return ERR; //index不在有效范围
    142     if (index==0){
    143         //头插
    144         tmp->next=*L; //将新结点的指针区指向链表的头结点,随之,新节点变成链表的头结点
    145         tmp->data=node_to_insert; //数据区
    146         *L=tmp; //将原来指向头结点的指针修改为现在的新头结点
    147         return OK;
    148     }
    149     if (index>getLength(*L)-1){
    150         //尾插
    151         tmp->next=NULL; //因为是尾插,此结点是链表的最后一个结点,所以指针区为NULL
    152         tmp->data=node_to_insert; //数据区
    153         p=*L; //变量p用于遍历
    154         while (p){
    155             //寻找当前线性表的最后一个结点,用于将新结点附在它的后面
    156             if (p->next==NULL)
    157                 //找到了当前链表的最后一个
    158                 break;
    159             p=p->next; //继续下一个结点
    160         }
    161         p->next=tmp; //将原来线性表的最后一个结点指向新的尾结点
    162         return OK;
    163     }
    164     //不是头插也不是尾插
    165     k=0;
    166     p=*L;
    167     for (k=0; k<index-1; k++){
    168         //遍历到第index个结点的前一个结点,头结点的index等于0
    169         //利用index的前一个结点的next就可以知道第index个结点
    170         p=p->next;
    171     }
    172     tmp->next=p->next; //把tmp接到index前面
    173     p->next=tmp; //再把tmp接到index前一个结点的后面
    174     tmp->data=node_to_insert; //数据区
    175     return OK;
    176 }
    177 status delete(LinkList **L, int index){
    178     //当index=0时,即头删
    179     //当index=getLength(root)-1时,即尾删
    180     int k;
    181     LinkList * p,* q;
    182     if (index<0) return ERR; //index不在有效范围
    183     if (index==0){
    184         //头删
    185         p=(*L)->next; //先将原来的头结点的下一个结点的指针保存起来
    186         free(*L); //释放原来的头结点
    187         *L=p; //将原来指向头结点的指针修改为现在的新头结点
    188         return OK;
    189     }
    190     if (index>getLength(*L)-2){
    191         //尾删
    192         p=*L; //变量p用于遍历
    193         while (p){
    194             //寻找当前线性表的最后一个结点的前一个结点,将这个结点的后一个结点(即最后一个结点)删除
    195             if (p->next->next==NULL)
    196                 //找到
    197                 break;
    198             p=p->next; //继续下一个结点
    199         }
    200         free(p->next); //将原来线性表的最后一个结点删除
    201         p->next=NULL; //将原来的倒数第二个结点变成尾结点
    202         return OK;
    203     }
    204     //不是头插也不是尾插
    205     p=*L;
    206     for (k=0; k<index-1; k++){
    207         //遍历到第index个结点的前一个结点,头结点的index等于0
    208         //利用index的前一个结点的next就可以知道第index个结点
    209         p=p->next;
    210     }
    211     q=p->next;
    212     p->next=p->next->next; //将index前一个结点和后一个结点相连
    213     free(q); //删除index的结点
    214     return OK;
    215 }
    216 void showList(LinkList *L){
    217     int i;
    218     int total=getLength(L);
    219     LinkList * p=L;
    220     for (i=0; i<total; i++){
    221         printf("%c	",p->data); p=p->next;
    222     }
    223 }
    224 
    225 /*
    226     链式存储结构的线性表的优缺点:(注意,上述实现的链式线性表叫做单链表)
    227     优点:
    228         1.插入和删除的时间复杂度是0(1)
    229         2.存储空间不受预设限制
    230     缺点:
    231         1.寻找某个结点需要进行遍历操作
    232     另外,
    233         把单链表的尾结点的指针区指向头结点,便成为循环链表;
    234         把单链表的每个结点再增加一个指针区,新加的指针区指向前一个结点,便成为双向链表
    235 */
    236 /* 环境: Code::Blocks with GCC 5.1 */

    运行截图:

  • 相关阅读:
    [CF703D] Mishka and Interesting sum
    [CF1454F] Array Partition
    [CF13E] Holes
    [CF1110D] Jongmah
    [CF1204D2] Kirk and a Binary String
    [CF936B] Sleepy Game
    [CF546E] Soldier and Traveling
    [CF1025D] Recovering BST
    [CF598C] Nearest vectors
    [CF988E] Divisibility by 25
  • 原文地址:https://www.cnblogs.com/ryzz/p/12215331.html
Copyright © 2011-2022 走看看