數據結構中邏輯結構分線性和非線性。數據結構
線性表即爲線性結構中的一種。
測試
線性表的特性 百度百科解釋在此。url
我的總結爲 善始善終,順序排列,首尾不相連(像火車同樣)。spa
線性表的基本操做以下:code
初始化,銷燬,重置爲空表,判斷是否爲空,查找表的長度,element
查找元素的位置,根據位置查找元素,查找元素的上一個元素,查找元素的下一個元素,get
插入元素,刪除元素,遍歷元素。it
下面是順序存儲結構的C實現。(有時間能夠嘗試下鏈式存儲結構的實現)io
#include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INIT_SIZE 10 //初始化表長度 #define INCREMENT_SIZE 5 //增量 typedef int Status; typedef int Elemtype; /* * 數據存貯結構 */ typedef struct { Elemtype *elem; //存儲空間基址 int length; //當前長度 int size; //當前分配的表長大小 }SqList; /* * 初始化線性表 */ Status InitList(SqList *L) { L->elem = (Elemtype *) malloc(INIT_SIZE * sizeof(Elemtype)); if (!L->elem) { return ERROR; } L->length = 0; L->size = INIT_SIZE; return OK; } /* * 銷燬 */ Status DestroyList(SqList *L) { free(L->elem); L->length = 0; L->size = 0; return OK; } /* * 清空 */ Status ClearList(SqList *L) { L->length = 0; return OK; } /* * 是否爲空 */ Status isEmpty(const SqList L) { if (0 == L.length) { return TRUE; } else { return FALSE; } } /* * 獲取表長 */ Status getLength(const SqList L) { return L.length; } /* * 獲取指定位置的元素 */ Status GetElem(const SqList L, int i, Elemtype *e) { if (i < 1 || i > L.length) { return ERROR; } *e = L.elem[i-1]; return OK; } /* * 比較元素大小 */ Status compare(Elemtype e1, Elemtype e2) { if (e1 == e2) { return 0; } else if (e1 < e2) { return -1; } else { return 1; } } /* * 查找元素的位置 */ Status FindElem(const SqList L, Elemtype e, Status (*compare)(Elemtype, Elemtype)) { int i; for (i = 0; i < L.length; i++) { if (!(*compare)(L.elem[i], e)) { return i + 1; } } if (i >= L.length) { return ERROR; } } /* * 查找當前元素的前一個元素 */ Status PreElem(const SqList L, Elemtype cur_e, Elemtype *pre_e) { int i; for (i = 0; i < L.length; i++) { if (cur_e == L.elem[i]) { if (i != 0) { *pre_e = L.elem[i - 1]; } else { return ERROR; } } } if (i >= L.length) { return ERROR; } } /* * 查找當前元素的下一個元素 */ Status NextElem(const SqList L, Elemtype cur_e, Elemtype *next_e) { int i; for (i = 0; i < L.length; i++) { if (cur_e == L.elem[i]) { if (i < L.length - 1) { *next_e = L.elem[i + 1]; return OK; } else { return ERROR; } } } if (i >= L.length) { return ERROR; } } /* * 插入元素 */ Status InsertElem(SqList *L, int i, Elemtype e) { Elemtype *new; if (i < 1 || i > L->length + 1) { return ERROR; } if (L->length >= L->size) { new = (Elemtype*) realloc(L->elem, (L->size + INCREMENT_SIZE) * sizeof(Elemtype)); if (!new) { return ERROR; } L->elem = new; L->size += INCREMENT_SIZE; } Elemtype *p = &L->elem[i - 1]; Elemtype *q = &L->elem[L->length - 1]; for (; q >= p; q--) { *(q + 1) = *q; } *p = e; ++L->length; return OK; } /* * 刪除元素 */ Status DeleteElem(SqList *L, int i, Elemtype *e) { if (i < 1 || i > L->length) { return ERROR; } Elemtype *p = &L->elem[i - 1]; *e = *p; for (; p < &L->elem[L->length]; p++) { *(p) = *(p + 1); } --L->length; return OK; } /* * 訪問元素 */ void visit(Elemtype e) { printf("%d ", e); } /* * 遍歷表 */ Status TraverseList(const SqList L, void (*visit)(Elemtype)) { int i; for(i = 0; i < L.length; i++) { visit(L.elem[i]); } return OK; } //測試 int main() { SqList L; if (InitList(&L)) { Elemtype e; printf("init_success\n"); int i; for (i=0; i<10; i++) { InsertElem(&L, i+1, i); } printf("length is %d\n", getLength(L)); if (GetElem(L, 1, &e)) { printf("This first element is %d\n", e); } else { printf("element id not exist\n"); } printf("The 5 at %d\n", FindElem(L, 5, *compare)); PreElem(L, 6, &e); printf("The 6's previoud element is %d\n",e); NextElem(L, 6, &e); printf("The 6's next element is %d\n", e); DeleteElem(&L, 1, &e); printf("delete first element is %d\n",e); TraverseList(L, visit); if (DestroyList(&L)) { printf("\ndestory_success"); } } }
看了幾遍 終於通了,對新手來講其中比較難理解的地方就是插入元素 那個操做裏的 位移操做 舉例以下class
list 裏本來有 1 2 3 4 5 當須要插入 6 到 第二個位置 須要把 2 3 4 5 都日後移動 可是在上面的代碼裏移動的是元素地址 從最後一個開始 從高位往地位移動 因此比較難理解。