数据结构中逻辑结构分线性和非线性。数据结构
线性表即为线性结构中的一种。
测试
线性表的特性 百度百科解释在此。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 都日后移动 可是在上面的代码里移动的是元素地址 从最后一个开始 从高位往地位移动 因此比较难理解。