資料結構 C語言 線性表 順序表 實現
阿新 • • 發佈:2019-01-04
#include<stdio.h> #include<stdlib.h > /* C提供三種預處理。巨集定義、檔案包含、條件編譯 。 巨集 定 義:又稱為巨集代換、巨集替換,簡稱“巨集”。巨集定義格式:#define 識別符號 字串 檔案包含:#include<***.h>或者 #include“***.h(.c)” 條件編譯:(#ifndef 和 #endif 成對出現)作用:避免兩個欄位中間的預處理重複處理。 */ #ifndef STATUS_H #define STATUS_H #define TRUE 1 //真 #define FALSE 0 //假 #define YES 1 //是 #define NO 0 //否 #define OK 1 //通過 #define ERROR 0 //錯誤 #define SUCCESS 1 //成功 #define UNSUCCESS 0 //失敗 #define INFEASIBLE -1 //不可行 #ifndef _MATH_H_ //系統中已有此狀態碼定義,要避免衝突 #define OVERFLOW -2 //堆疊上溢 #define UNDERFLOW -3 //堆疊下溢 #endif /* 狀態碼識別型別 */ typedef int Status; /* 巨集函式(使用define進行多行定義時要加\)*/ //函式暫停一段時間 #define Wait(x)\ {\ double _Loop_Num_;\ for(_Loop_Num_=0.01; _Loop_Num_<=100000.0*x; _Loop_Num_+=0.01);\ }//設立一個空迴圈 //摁Enter鍵繼續 #define PressEnter\ {\ fflush(stdin);\ printf("Press Enter...");\ getchar();\ fflush(stdin);\ }//fflush清空標準輸入流stdin /* getchar()函式等待輸入,直到按回車才結束。回車前的所有輸入字元都會逐個顯示在螢幕 但只有第一個字元作為函式的返回值。利用getchar函式讓程式除錯執行結束後 等待程式設計者按下鍵盤才返回編輯介面。 */ #endif #define LIST_INIT_SIZE 100 //定義線性順序表的容量置為100 #define LISTINCREMENT 10 //定義線性順序表的遞增量置為10 typedef int LElemType_Sq; //定義線性順序表型別的別名 typedef struct SqList //定義線性順序表的結構體並起名為SqList { LElemType_Sq *elem; //表的首地址 int length; //表的當前長度 int listsize; //表的容量 } SqList; //順序表相關操作列表------------------------------------------------------------ Status InitList_Sq(SqList *L) { //建立一個線性順序表-------------------------------------------------------1 (*L).elem = (LElemType_Sq*)malloc(LIST_INIT_SIZE*sizeof(LElemType_Sq)); if(!(*L).elem) exit(OVERFLOW); (*L).length = 0; (*L).listsize = LIST_INIT_SIZE; return OK; } void ClearList_Sq(SqList *L) { //清除線性順序表內容-------------------------------------------------------2 (*L).length = 0; } void DestroyList_Sq(SqList *L) { //銷燬線性順序表-----------------------------------------------------------3 free((*L).elem); (*L).elem = NULL; (*L).length = 0; (*L).listsize = 0; } Status ListEmpty_Sq(SqList L) { //判斷線性順序表是否為空---------------------------------------------------4 return L.length==0 ? TRUE : FALSE; } int ListLength_Sq(SqList L) { //返回該線性順序表的長度---------------------------------------------------5 return L.length; } Status GetElem_Sq(SqList L, int i, LElemType_Sq *e) { //取得該線性順序表確定位置的內容並賦予e------------------------------------6 if(i<1 || i>L.length) return ERROR; else *e = L.elem[i-1]; return OK; } int LocateElem_Sq(SqList L, LElemType_Sq e, Status(*Compare)(LElemType_Sq, LElemType_Sq)) { //線上性順序表中找到與e等值的位置,並返回----------------------------------7 int i = 1; while(i<=L.length && !Compare(e, L.elem[i-1])) ++i; if(i<=L.length) return i; else return 0; } Status PriorElem_Sq(SqList L, LElemType_Sq cur_e, LElemType_Sq *pre_e) { //若cur_e不是線性順序表的第一個並且在表中存在與之相同的內容----------------8 int i = 1; if(L.elem[0]!=cur_e) { while(i<L.length && L.elem[i]!=cur_e) ++i; if(i<L.length) { *pre_e = L.elem[i-1]; return OK; } } return ERROR; } Status NextElem_Sq(SqList L, LElemType_Sq cur_e, LElemType_Sq *next_e) { //若cur_e不是線性順序表的最後一個並且在表中存在與之相同的內容--------------9 int i = 0; while(i<L.length && L.elem[i]!=cur_e) ++i; if(i<L.length-1) { *next_e = L.elem[i+1]; return OK; } return ERROR; } Status ListInsert_Sq(SqList *L, int i, LElemType_Sq e) { //線上性順序表位序i的前面插入e元素----------------------------------------10 LElemType_Sq *newbase; LElemType_Sq *p, *q; if(i<1 || i>(*L).length+1) return ERROR; if((*L).length >= (*L).listsize) { newbase = (LElemType_Sq*)realloc((*L).elem, ((*L).listsize+LISTINCREMENT)*sizeof(LElemType_Sq)); if(!newbase) exit(OVERFLOW); (*L).elem = newbase; (*L).listsize += LISTINCREMENT; } q = &(*L).elem[i-1]; for(p=&(*L).elem[(*L).length-1]; p>=q; --p) *(p+1) = *p; *q = e; (*L).length++; return OK; } Status ListDelete_Sq(SqList *L, int i, LElemType_Sq *e) { //刪除線性順序表位序為i的元素,並將之返回---------------------------------11 LElemType_Sq *p, *q; if(i<1||i>(*L).length)return ERROR; p = &(*L).elem[i-1]; *e = *p; q = (*L).elem+(*L).length-1; for(++p; p<=q; ++p) *(p-1) = *p; (*L).length--; return OK; } Status ListTraverse_Sq(SqList L, void(*Visit)(LElemType_Sq)) { //遍歷輸出整個線性順序表--------------------------------------------------12 int i; for(i=0; i<L.length; i++) Visit(L.elem[i]); return OK; } //函式指標---------------------------------------------------------------------- Status Compare(LElemType_Sq e, LElemType_Sq data) //Compare指標函式的實現 { return data==e ? TRUE : FALSE; } void PrintElem(LElemType_Sq e) //visit指標函式的實現 { printf("%d ", e); } //求並集相關函式---------------------------------------------------------------- Union(SqList *La, SqList Lb) { //合併兩個非遞減線性表成新的非遞減排列線性(A=A∪B)------------------------13 int La_len, Lb_len; int i; LElemType_Sq e; La_len = ListLength_Sq(*La); Lb_len = ListLength_Sq(Lb); for(i=1; i<=Lb_len; i++) { GetElem_Sq(Lb, i, &e); if(!LocateElem_Sq(*La, e, Compare)) ListInsert_Sq(La, ++La_len, e); } } Status equal(SqList e1, SqList e2) { //判斷兩個函式相等否------------------------------------------------------14 if (e1.length != e2.length) return FALSE; else { int i; for (i=0 ; i<e1.length; i++) { if(e1.elem[i] != e2.elem[i]) { return FALSE; } } if (i >= e1.length) { return TRUE; } } } //順序表歸併相關操作------------------------------------------------------------ void MergeSqList_1(SqList La, SqList Lb, SqList *Lc) { //呼叫順序表函式進行合併--------------------------------------------------15 int La_len, Lb_len; int i, j, k; LElemType_Sq ai, bj; i = j = 1; k = 0; InitList_Sq(Lc); La_len = ListLength_Sq(La); Lb_len = ListLength_Sq(Lb); while(i<=La_len && j<=Lb_len) { GetElem_Sq(La, i, &ai); GetElem_Sq(Lb, j, &bj); if(ai<=bj) { ListInsert_Sq(Lc, ++k, ai); i++; } else { ListInsert_Sq(Lc, ++k, bj); j++; } } while(i<=La_len) { GetElem_Sq(La, i++, &ai); ListInsert_Sq(Lc, ++k, ai); } while(j<=Lb_len) { GetElem_Sq(Lb, j++, &bj); ListInsert_Sq(Lc, ++k, bj); } } void MergeSqList_2(SqList La, SqList Lb, SqList *Lc) { //呼叫順序表函式進行合併--------------------------------------------------16 LElemType_Sq *pa, *pb, *pc; LElemType_Sq *pa_last, *pb_last; pa = La.elem; pb = Lb.elem; (*Lc).listsize = (*Lc).length = La.length + Lb.length; pc = (*Lc).elem = (LElemType_Sq *)malloc((*Lc).listsize*sizeof(LElemType_Sq)); if(!pc) exit(OVERFLOW); pa_last = La.elem + La.length - 1; pb_last = Lb.elem + Lb.length - 1; while(pa<=pa_last && pb<=pb_last) { if(*pa <= *pb) *pc++ = *pa++; else *pc++ = *pb++; } while(pa <= pa_last) *pc++ = *pa++; while(pb <= pb_last) *pc++ = *pb++; } //主函式------------------------------------------------------------------------ int main() { SqList L; int i; LElemType_Sq e; printf("▼1\n▲函式 InitList_Sq 測試...\n"); //1.函式InitList_Sq測試 { printf("初始化順序表 L ...\n"); InitList_Sq(&L); printf("\n"); } PressEnter; printf("▼4\n▲函式 ListEmpty_Sq 測試...\n"); //4.函式ListEmpty_Sq測試 { ListEmpty_Sq(L) ? printf(" L 為空!!\n") : printf(" L 不為空!\n"); printf("\n"); } PressEnter; printf("▼10\n▲函式 ListInsert_Sq 測試...\n"); //10.函式ListInsert_Sq測試 { for(i=1; i<=6; i++) { printf("作為示範,在 L 第 %d 個位置插入 \"%d\"...\n", i, 2*i); ListInsert_Sq(&L, i, 2*i); } printf("\n"); } PressEnter; printf("▼12\n▲函式 ListTraverse_Sq 測試...\n"); //12.函式ListTraverse_Sq測試 { printf(" L 中的元素為:L = "); ListTraverse_Sq(L, PrintElem); printf("\n\n"); } PressEnter; printf("▼5\n▲函式 ListLength_Sq 測試...\n"); //5.函式ListLength_Sq測試 { i = ListLength_Sq(L); printf(" L 的長度為 %d \n", i); printf("\n"); } PressEnter; printf("▼11\n▲函式 ListDelete_Sq 測試...\n"); //11.函式ListDelete_Sq測試 { ListDelete_Sq(&L, 6, &e); printf("刪除 L 中第 6 個元素 \"%d\" ...\n", e); printf(" L 中的元素為:L = "); ListTraverse_Sq(L, PrintElem); printf("\n\n"); } PressEnter; printf("▼6\n▲函式 GetElem_Sq 測試...\n"); //6.函式GetElem_Sq測試 { GetElem_Sq(L, 4, &e); printf(" L 中第 4 個位置的元素為 \"%d\" \n", e); printf("\n"); } PressEnter; printf("▼7\n▲函式 LocateElem_Sq 測試...\n"); //7.函式LocateElem_Sq測試 { i = LocateElem_Sq(L, 7, Compare); printf(" L 中第一個元素值大於 \"7\" 的元素的位置為 %d \n", i); printf("\n"); } PressEnter; printf("▼8\n▲函式 PriorElem_Sq 測試...\n"); //8.函式PriorElem_Sq測試 { PriorElem_Sq(L, 6, &e); printf("元素 \"6\" 的前驅為 \"%d\" \n", e); printf("\n"); } PressEnter; printf("▼9\n▲函式 NextElem_Sq 測試...\n"); //9.函式NextElem_Sq測試 { NextElem_Sq(L, 6, &e); printf("元素 \"6\" 的後繼為 \"%d\" \n", e); printf("\n"); } PressEnter; printf("▼2\n▲函式 ClearList_Sq 測試...\n"); //2.函式ClearList_Sq測試 { printf("清空 L 前:"); ListEmpty_Sq(L) ? printf(" L 為空!!\n") : printf(" L 不為空!\n"); ClearList_Sq(&L); printf("清空 L 後:"); ListEmpty_Sq(L) ? printf(" L 為空!!\n") : printf(" L 不為空!\n"); printf("\n"); } PressEnter; printf("▼3\n▲函式 DestroyList_Sq 測試...\n"); //3.函式DestroyList_Sq測試 { printf("銷燬 L 前:"); L.elem ? printf(" L 存在!\n") : printf(" L 不存在!!\n"); DestroyList_Sq(&L); printf("銷燬 L 後:"); L.elem ? printf(" L 存在!\n") : printf(" L 不存在!!\n"); printf("\n"); } PressEnter; printf("▼13\n▲函式 Union 測試...\n"); SqList La, Lb; LElemType_Sq a[] = {3, 5, 8, 11, 12}; LElemType_Sq b[] = {2, 4, 6, 7, 9, 10, 13}; InitList_Sq(&La); //建立線性順序表La InitList_Sq(&Lb); //建立線性順序表Lb for(i=1; i<=5; i++) ListInsert_Sq(&La, i, a[i-1]); //初始化La for(i=1; i<=7; i++) ListInsert_Sq(&Lb, i, b[i-1]); //初始化Lb printf("La = "); //輸出La ListTraverse_Sq(La, PrintElem); printf("\n"); printf("Lb = "); //輸出Lb ListTraverse_Sq(Lb, PrintElem); printf("\n\n"); printf("La = La∪Lb = "); //輸出新表La的內容 Union(&La,Lb); ListTraverse_Sq(La, PrintElem); printf("\n\n"); PressEnter; printf("▼14\n▲函式 equal 測試...\n"); equal(La,Lb)?printf("表La和Lb相等\n"):printf("表La和Lb不相等\n"); equal(La,La)?printf("表La和La相等\n"):printf("表La和La不相等\n"); PressEnter; printf("▼15\n▲函式 MergeSqList_1 測試...\n"); SqList Lc1; InitList_Sq(&La); InitList_Sq(&La); //初始化La for(i=1; i<=5; i++) ListInsert_Sq(&La, i, a[i-1]); InitList_Sq(&Lb); //初始化Lb for(i=1; i<=7; i++) ListInsert_Sq(&Lb, i, b[i-1]); MergeSqList_1(La, Lb, &Lc1); //合併A與B,演算法2.6 printf("合併La和Lb為Lc1 = "); //輸出Lc1 ListTraverse_Sq(Lc1, PrintElem); printf("\n\n"); PressEnter; printf("▼16\n▲函式 MergeSqList_2 測試...\n"); SqList Lc2; InitList_Sq(&La); InitList_Sq(&La); //初始化La for(i=1; i<=5; i++) ListInsert_Sq(&La, i, a[i-1]); InitList_Sq(&Lb); //初始化Lb for(i=1; i<=7; i++) ListInsert_Sq(&Lb, i, b[i-1]); MergeSqList_2(La, Lb, &Lc2); //合併A與B,演算法2.6 printf("合併La和Lb為Lc2 = "); //輸出Lc1 ListTraverse_Sq(Lc2, PrintElem); printf("\n\n"); PressEnter; return 0; }