• 线性表的顺序存储


     线性表的顺序存储,其数据结构以及具体实现详见下面代码,重要知识点全部以注释的形式在代码中展示出来。

      1 /***
      2 线性表的顺序存储结构是一种 随机存取 的存储结构
      3 在线性顺序表中插入或者删除一个元素,时间都消耗在移动元素上,平均约移动一般的元素,
      4 故ListInsert和ListDelete的时间复杂度都为O(n);
      5 */
      6 #include<stdio.h>
      7 #include<stdlib.h>
      8 //***************线性表的动态分配顺序存储结构*****************
      9 #define LIST_INIT_SIZE 100  //线性表存储空间的初始分配量
     10 #define LISTINCREMENT  10   //线性表存储空间的存储增量
     11 typedef struct
     12 {
     13     int *elem;   //数组指针,存储空间基址
     14     int length;  //当前长度
     15     int listsize;//当前分配的存储容量(以sizeof(int)为单位)
     16 }SqList;
     17 
     18 //******************初始化线性表,构造一个空表********************
     19 void InitList(SqList &L)
     20 {
     21     L.elem = (int *)malloc(LIST_INIT_SIZE * sizeof(int));
     22     if (!L.elem)
     23     {
     24         printf("存储分配失败,任意键退出!
    ");
     25         getchar();
     26         exit(1);
     27     }
     28     L.length = 0;
     29     L.listsize = LIST_INIT_SIZE;
     30 }
     31 
     32 //*********************输出线性表中的数据**************************
     33 void PrintList(SqList L)
     34 {
     35     int *p = L.elem; //顺序表的开始位置
     36     int *q = L.elem + L.length - 1;//顺序表的结束位置
     37     while(p<=q)
     38     {
     39         printf("%d ", *p++);
     40     }
     41 }
     42 
     43 //*************************线性表的插入****************************
     44 //*******参数i代表插入位置,在第i个之前插入*,故 1<=i<=n+1*********
     45 /**
     46 一般情况下,在第i(1<=i<=n)个元素之前插入,需要将第i至n(n-i+1)个元素向后移动一个位置,
     47 若i=n+1,则直接在插入在最后即可
     48 */
     49 void ListInsert(SqList &L,int i,int e)
     50 {
     51     //在顺序线性表L中的第i个位置之前插入新的元素e
     52     //i的合法值为1<=i<=ListLength(L)+1
     53     if (i<1||i>L.length+1)
     54     {
     55         printf("输入的插入位置不合法,请确定后重新输入!任意键退出
    ");
     56         getchar();
     57         exit(1);
     58     }
     59     if (L.length >= L.listsize)
     60     {
     61         //当前存储空间已满,需要增加分配
     62         int * newbase = (int *)realloc(L.elem,(L.listsize + LISTINCREMENT)*sizeof(int));
     63         if (!newbase)
     64         {
     65             printf("存储分配失败,任意键退出!
    ");
     66             getchar();
     67             exit(1);
     68         }
     69         L.elem = newbase;//新基址
     70         L.listsize += LISTINCREMENT;//增加存储容量
     71     }
     72     int * q = &(L.elem[i-1]);//q为插入位置
     73     for (int * p = &(L.elem[L.length-1]); p >= q; --p)
     74     {
     75         *(p+1) = *p;//插入位置及其之后的元素右移
     76     }
     77     *q = e;//插入e
     78     ++L.length;//表长加1
     79 }
     80 
     81 //***************************顺序线性表的删除******************************
     82 /**
     83 参数i代表删除位置,1<=i<=n,和插入时i的取值范围不同
     84 一般情况下,删除第i(1<=i<=n)个元素时需要将从第i+1至第n(n-i)个元素依次向前移动一个位置
     85 */
     86 void ListDelete(SqList &L,int i)
     87 {
     88     //删除顺序线性表中的第i个元素,i的合法值为1<=i<=ListLength(L)
     89     if (i<1 || i>L.length)
     90     {
     91         printf("输入的删除位置不合法,请确定后重新输入!任意键退出!
    ");
     92         getchar();
     93         exit(1);
     94     }
     95     int * p = &(L.elem[i-1]);//p为删除位置
     96     int * q = L.elem + L.length - 1;//q为表尾位置
     97     for (++p ; p<=q; ++p)
     98     {
     99         *(p-1) = *p;//被删除元素之后的元素左移
    100     }
    101     --L.length;//表长减1
    102 }
    103 
    104 //************数值定位函数,返回元素e在L中的位置,若没有,返回0***************
    105 int LocateElem(SqList L,int e)
    106 {
    107     //在顺序线性表中查找第一个与元素e相同位序
    108     //若找到,则返回其在L中的位序,否则返回0
    109     int i = 1;//i的初始值为第一个元素的位序
    110     int *p = L.elem ;//p的初始值为第一个元素的存储位置
    111     while(i<=L.length && e != *p)
    112     {
    113         ++i;
    114         ++p;
    115     }
    116     if (i<=L.length)
    117         return i;
    118     else
    119         return 0;
    120 }
    121 
    122 //**********************取出指定位序的线性表中的数据元素***********************
    123 int GetElem(SqList L,int i)
    124 {
    125     //将线性表L中的第i个元素返回给e
    126     if (i<1 || i>L.length)
    127     {
    128         printf("该数据元素不存在,请仔细确认!任意键退出
    ");
    129         getchar();
    130         exit(1);
    131     }
    132     // int *q = &L.elem[i-1];
    133     // int e = *q;
    134     int e = L.elem[i-1];
    135     //因为elem是一个数组指针,当只用elem时,代表首地址
    136     //,若具体指定某一个数elem[i],则代表第i+1个元素,故下面和上面的注释方法都可行
    137     // int *p = L.elem;
    138     // int e = *(p+i-1);
    139     return e;
    140 
    141 }
    142 
    143 //****************************线性顺序表的合并********************************
    144 /**
    145 该方法的线性复杂度为O(ListLength(LA) x ListLength(LB) )
    146 该方法得到的线性表是无序的,数据直接插在一个线性表的最后
    147 是将所有在线性表Lb中但不在La中的数据元素插入到La中,无重复项
    148 */
    149 void ListUnoin(SqList &La,SqList Lb)
    150 {
    151     //将所有在线性表Lb中但不在La中的数据元素插入到La中
    152     int la_len = La.length;
    153     int lb_len = Lb.length;
    154     int e;
    155     for (int i = 1; i <= lb_len; ++i)
    156     {
    157         e = GetElem(Lb,i);//取Lb中第i个元素赋值给e
    158         //printf("%d
    ",e);
    159         if(!LocateElem(La,e))
    160         {
    161             ListInsert(La,++la_len,e);//将数据插在La的末尾
    162         }
    163     }
    164 }
    165 
    166 //**************************有序线性顺序表的合并*******************************
    167 /**
    168 通过增加一个线性表,使得时间复杂度由O(ListLength(LA) x ListLength(LB))变成
    169 了O(ListLength(LA) + ListLength(LB))
    170 不过使用这种方法需要有个前提:La和Lb已经排序
    171 得到的结果Lc也是排好序的线性表
    172 */
    173 void MergeList(SqList La,SqList Lb,SqList &Lc)
    174 {
    175     //本例中以非递减排序为例
    176     int * pa = La.elem;
    177     int * pb = Lb.elem;
    178     Lc.length = La.length + Lb.length;
    179     Lc.listsize = Lc.length;
    180     Lc.elem = (int *)malloc(Lc.listsize * sizeof(int));
    181     if (!Lc.elem)
    182     {
    183         printf("存储分配失败,任意键退出!
    ");
    184         getchar();
    185         exit(1);
    186     }
    187     int *pc = Lc.elem;
    188     int *pa_last = La.elem + La.length - 1;
    189     int *pb_last = Lb.elem + Lb.length - 1;
    190     while(pa<=pa_last && pb<=pb_last)//归并操作
    191     {
    192         if(*pa <= *pb)
    193             *pc++ = *pa++;
    194         else
    195             *pc++ = *pb++;
    196     }
    197     while(pa <= pa_last)
    198         *pc++ = *pa++;//插入La的剩余元素
    199     while(pb <= pb_last)
    200         *pc++ = *pb++;//插入Lb的剩余元素
    201 }
    202 
    203 
    204 int  main()
    205 {
    206     //首先输入10个数据,构造一个线性表,测试建表,输出,插入,删除功能是否正确
    207     SqList La,Lb,Lc;
    208     InitList(La);
    209     InitList(Lb);
    210     InitList(Lc);
    211     int count,value,location;
    212     printf("请输入建立顺序表La的元素个数:");
    213     scanf("%d",&count);
    214     printf("请依次输入%d个数据:",count);
    215     for (int i = 0; i < count; ++i)
    216     {
    217         //将输入的数据插入到顺序表La中
    218         scanf("%d",&value);
    219         ListInsert(La,i+1,value);
    220     }
    221     //输出线性表的数据
    222     printf("该顺序线性表的数据元素为:");
    223     PrintList(La);
    224 
    225     //测试插入数据是否可行
    226     printf("
    请输入插入位置和插入值:");
    227     scanf("%d%d",&location,&value);
    228     ListInsert(La,location,value);
    229     printf("插入之后的数据元素为:");
    230     PrintList(La);
    231 
    232     //测试删除数据情况
    233     printf("
    请输入删除位置:");
    234     scanf("%d",&location);
    235     ListDelete(La,location);
    236     printf("数据删除之后的元素为:" );
    237     PrintList(La);
    238 
    239     //测试顺序表的合并,需要两个有序的顺序表
    240     printf("
    请输入建立顺序表Lb的元素个数:");
    241     scanf("%d",&count);
    242     printf("请依次输入%d个数据:",count);
    243     for (int i = 0; i < count; ++i)
    244     {
    245         //将输入的数据插入到顺序表La中
    246         scanf("%d",&value);
    247         ListInsert(Lb,i+1,value);
    248     }
    249     MergeList(La,Lb,Lc);
    250     printf("将La和Lb合并之后的Lc数据元素为:");
    251     PrintList(Lc);
    252 
    253     printf("
    采用时间复杂度更高的合并方式为:");
    254     ListUnoin(La,Lb);
    255     PrintList(La);
    256 
    257     return 0;
    258 }
     
  • 相关阅读:
    java内部类
    接口与继承
    数据结构
    数据I/O流
    课程总结
    第六次实训作业异常处理
    常用类的课后作业
    窗口实训1
    实训作业4
    实训作业3
  • 原文地址:https://www.cnblogs.com/wujiyang/p/4334357.html
Copyright © 2020-2023  润新知