老郭帶你學數據結構(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: \n");
 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: \n", 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("表已滿!\n");
 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\t", 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("表不爲空\n");
14     }    
15     ListPrint(sqlist);
16     ListInsert(&sqlist, 3, 9);
17     if(!ListFull(sqlist)){
18         printf("表沒有滿\n");
19     }
20     ListPrint(sqlist);
21     printf("表的長度爲:%d\n", (sqlist).len);
22     int i = ListDelete(&sqlist,3);
23     ListPrint(sqlist);
24     printf("%d\n", 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可執行文件,由於每次都是同一個名字,會相互覆蓋,建議取一個由意義的名字

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章