zoukankan      html  css  js  c++  java
  • 老郭带你学数据结构(C语言系列)1-线性表之静态顺序表

    在学习之前,先说下我的软件情况,操作系统是manjaro linux 今天刚刚升级的,编辑器是vim8.0.55,编译器是gcc 6.2.1,调试器是gdb 7.12,版本再低点也可以,只要gcc版本是5以上,就应该问题不大。

    一、基本概念:

      线性表:由n个类型相同的数据元素组成的有限序列,记为(a1,a2,……an)。

      线性表的特征:其中的元素存在这序偶关系,元素之间存在着严格的次序关系。

      顺序存储表:线性表中的元素依次存放在一组地址连续的存储单元(数组)中。

      存储特点:若已知首元素的起始地址a0和每个元素占用的空间m,则计算第i个元素的存储位置:ai = a0 + (i - 1)m。

      顺序表的特征:(1)在逻辑上相邻的元素,在物理上也是相邻

                                (2)知道表中起始元素的地址,线性表中的任一个元素地址都可以确定,因此很容易实现对线性表中的元素的随机访问。

    二、代码实现:

    1)结构实现(行号是为了阅读和说明代码方便,请复制代码是忽略行号)

     1 typedef int ElemType;                                                 
     2
     3
     4 #define MAX 100
     5 struct sqList{
     6     ElemType data[MAX];
     7     int len;
     8 } ;

    说明:第1行是定义一种数据类型,方便以后让线性表的适用范围更广;

               第4行是定义表的大小,方便以后修改;

               第5-8行是定义一个结构体,其中封装了线性表的存储结构与线性表的大小;

            

    2)抽象数据类型(主要是为了说明定义的结构(本例中是顺序表)支持的运算操作,为了使用上的方便,建议使用头文件加实现的方式来运用)

    10 struct sqList;
    11 typedef struct sqList SqList;
    12
    13 //初始化线性表
    14 void ListInit(SqList *list);
    15
    16 //判断线性表是否为空,为空返回1,不为空返回0
    17 int ListEmpty(SqList list);
    18
    19 //判断线性表是否已满,已满返回1,未满返回0
    20 int ListFull(SqList list);
    21
    22 //创建线性表,根据提示,先输入表的长度,再根据提示依次输入表元素的值,>   成功输出0,不成功输出为-1
    23 void ListCreate(SqList *list);
    24
    25 //求取线性表的长度
    26 int ListLength(SqList list);
    27
    28 //查找指定元素值是否在表中,成功返回下标,不成功则返回0
    29 int LocateElem(SqList list, ElemType elem);
    30
    31 //线性表中插入指定位置,值已知的元素
    32 void ListInsert(SqList *list, int i, ElemType elem);
    33
    34 //删除线性表中的元素,并返回删除位置的值
    35 int ListDelete(SqList *list, int i);
    36
    38 int37 //访问数据元素算法实现
    38 int ListVisit(SqList list, int i);
    39
    40 //输出线性表元素
    41 void ListPrint(SqList list);
    42 #endif

    说明:第10行是声明一个线性表的结构体变量sqList;

               第11行使用了typedef的定义,以后可以使用SqList sqList就可以声明一个名称为sqList的结构体;

               第13-41行线性表支持的运算操作,每个方法都有注释,参数也比较简单明了,就不再多说

    3)头文件实现

    将1)和2)中的代码整合后,在第4行加上#ifndef SqList_H,在第42行加上#endif,实际项目中这样作是为了避免重复定义和引用头文件,文件名为SqList.h,完整代码如下:

     1 typedef int ElemType;
     2 #ifndef SqList_H
     3
     4 #define MAX 100
     5 typedef struct sqList{
     6     ElemType data[MAX];
     7     int len;
     8 } SqList;
     9
    10 struct sqList;
    11 typedef struct sqList SqList;
    12
    13 //初始化线性表
    14 void ListInit(SqList *list);
    15
    16 //判断线性表是否为空,为空返回1,不为空返回0
    17 int ListEmpty(SqList list);
    18
    19 //判断线性表是否已满,已满返回1,未满返回0
    20 int ListFull(SqList list);
    21
    22 //创建线性表,根据提示,先输入表的长度,再根据提示依次输入表元素的值,成功输出0,不成
       功输出为-1
    23 void ListCreate(SqList *list);
    24
    25 //求取线性表的长度
    26 int ListLength(SqList list);
    27
    28 //查找指定元素值是否在表中,成功返回下标,不成功则返回0
    29 int LocateElem(SqList list, ElemType elem);
    30
    31 //线性表中插入指定位置,值已知的元素
    32 void ListInsert(SqList *list, int i, ElemType elem);
    33
    34 //删除线性表中的元素,并返回删除位置的值
    35 int ListDelete(SqList *list, int i);
    36
    37 //访问数据元素算法实现
    38 int ListVisit(SqList list, int i);
    39
    40 //输出线性表元素
    41 void ListPrint(SqList list);
    42 #endif

    4)操作算法实现,实现头文件定义的顺序表的操作,文件名为SqList.c(注意头文件和和实现文件名字一模一样,只有后缀名由区别),具体代码如下:

      1 #include <stdio.h>
      2 #include "SqList.h"
      3
      4
      5                                                                                                                                                                                            
      6 //初始化线性表
      7 void ListInit(SqList *list){
      8     (*list).len = 0;
      9 }
     10
     11 //判断线性表是否为空,为空返回1,不为空返回0
     12 int ListEmpty(SqList list){
     13     if(0 == list.len){
     14         return 1;
     15     }
     16
     17     return 0;
     18 }
     19
     20 //判断线性表是否已满,已满返回1,未满返回0
     21 int ListFull(SqList list){
     22     if(MAX == list.len){
     23         return 1;
     24     }
     25
     26     return 0;
     27 }
     28
     29 //创建线性表,根据提示,先输入表的长度,再根据提示依次输入表元素的值,成功输出0,不成功输出为-1
     30 void ListCreate(SqList *list){
     31     int i;
     32     printf("please input the length of the list which you want to create: ");
     33     scanf("%d", &((*list).len));
     34     if((*list).len > MAX){
     35         return;
     36     }
     37     for(i = 0; i < (*list).len; i++){
     38         printf("please input NO %d element: ", i);
     39         scanf("%d", &((*list).data[i]));
     40     }
     41 }
     42
     43 //求取线性表的长度
     44 int ListLength(SqList list){
     45
     46     return list.len;
     47 }
     48
     49 //查找指定元素值是否在表中,成功返回下标,不成功则返回0
     50 int LocateElem(SqList list, ElemType elem){
     51     int i;
     52     for(i = 0; i < list.len; i++){
     53         if(list.data[i] == elem){
     54             return i+1;
     55         }
     56     }
     57
     58     return 0;
     59 }
     60
     61 //线性表中插入指定位置,值已知的元素
     62 void ListInsert(SqList *list, int i, ElemType elem){
     63     if(i < 0 || i > MAX){
     64         return;
     65     }
     66     if(1 == ListFull(*list)){
     67         printf("表已满! ");
     68     }
     69     for(int j = (*list).len; j >= i - 1; j--){
     70         (*list).data[j + 1] = (*list).data[j];
     71     }
     72     (*list).data[i - 1] = elem;
     73     (*list).len++;
     74 }
     75
     76 //删除线性表中的元素,并返回删除位置的值
     77 int ListDelete(SqList *list, int i){
     78     if(i < 0 || i > (*list).len){
     79         return -1;
     80     }
     81     if(ListEmpty(*list)){
     82         return -1;
     83     }
     84     int x = (*list).data[i - 1];
     85     for(int j = i - 1; j < (*list).len; j++){
     86         (*list).data[j] = (*list).data[j + 1 ];
     87     }
     88     (*list).len--;
     89
     90     return x;
     91 }
     92
     93 //访问数据元素算法实现
     94 int ListVisit(SqList list, int i){
     95     if(i < 0 || i > list.len){
     96         return -1;
     97     }
     98
     99     return list.data[i - 1];
    100 }
    101
    102 //输出线性表元素
    103 void ListPrint(SqList list){
    104     for(int i = 0; i < list.len; i++){
    105         printf("%d ", list.data[i]);
    106     }

    5)测试代码的实现,实现头文件是实现文件的整合应用,文件名可以随意,建议取得有意义,一般以test为前缀,我的文件名称testSqList.c,具体代码为:

       1 #include <stdio.h>                                                                                                                                                                          
     2 #include "SqList.h"
     3
     4
     5
     6 int main(int argc, char *argv)
     7 {
     8     SqList sqlist;
     9
    10     ListInit(&sqlist);
    11     ListCreate(&sqlist);
    12     if(!ListEmpty(sqlist)){
    13         printf("表不为空 ");
    14     }    
    15     ListPrint(sqlist);
    16     ListInsert(&sqlist, 3, 9);
    17     if(!ListFull(sqlist)){
    18         printf("表没有满 ");
    19     }
    20     ListPrint(sqlist);
    21     printf("表的长度为:%d ", (sqlist).len);
    22     int i = ListDelete(&sqlist,3);
    23     ListPrint(sqlist);
    24     printf("%d ", i);
    25
    26     return 0;
    27 }

    当然也可以自己实现其他的,数据结构代码的三个步骤如下:

    1、实现数据结构的逻辑结构与基本数据类型定义,规划合理的抽象数据类型,也就是数据结构支持的操作运算,并使用#ifndef...#endif方式实现头文件;

    2、实现抽象数据类型,并予以合理的实现;

    3、实现数据结构的测试,测试结构,符合要求,完工,否则继续重复1和2两个步骤,直到成功。

    6)补充说明:

    对多文件的编译,使用命令gcc testSqList.c SqList.c -o testSqList即可,也就是将多个需要的文件名放置在命令gcc和选项-o之间,后面的就是编译后的文件,可以省略,默认是a.out可执行文件,由于每次都是同一个名字,会相互覆盖,建议取一个由意义的名字

  • 相关阅读:
    (4)ES6解构赋值-字符串篇
    (3)ES6解构赋值-对象篇
    (2)ES6解构赋值-数组篇
    (1)ES6中let,const,对象冻结,跨模块常量,新增的全局对象介绍
    MySQL中char与varchar区别,varchar最大长度是多少?
    集成学习实战——Boosting(GBDT,Adaboost,XGBoost)
    集成学习——Boosting(GBDT,Adaboost,XGBoost)
    集成学习(Random Forest)——实践
    集成学习——Bagging
    决策树实践
  • 原文地址:https://www.cnblogs.com/guochaoxxl/p/6823116.html
Copyright © 2011-2022 走看看