在學習之前,先說下我的軟件情況,操作系統是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可執行文件,由於每次都是同一個名字,會相互覆蓋,建議取一個由意義的名字