c语言实现--顺序表操作
经过三天的时间终于把顺序表的操作实现搞定了。(主要是在测试部分停留了太长时间)
1;线性表顺序存储的概念:指的是在内存中用一段地址连续的存储单元依次存储线性表中的元素。
2;采用的实现方式:一段地址连续的存储单元可以用固定数组或者动态存储结构来实现,这里采用动态分配存储结构。
3;顺序表的定义及操作集合:头文件为defs.h
1 #ifndef _DEFS_H 2 #define _DEFS_H 3 4 #include<stdio.h> 5 #include<stdlib.h> 6 #include<malloc.h> 7 8 #define LIST_INIT_MAX 10 //长表为10 9 #define LIST_INCREMENT 2 //短表为2 10 typedef struct 11 { 12 int * elem; //采用动态存储分配结构 13 int length; 14 int listsize; 15 }sqlist; 16 //线性表操作集合 17 void InitList(sqlist *L); //初始化,动态分配一块存储空间 18 void DestroyList(sqlist *L); //释放这一段存储空间(撤销对应于动态) 19 void ClearList(sqlist *L); 20 void ListEmpty(sqlist L); 21 int ListLength(sqlist L); 22 int GetElem(sqlist L, int i, int *e); 23 void LocateList(sqlist L, int e); //在表中查找值为e的元素 24 int PriorElem(sqlist L, int cur_e, int *pri_e); //求当前元素的前驱 25 int NextElem(sqlist L, int cur_e, int *Nex_e); //求当前元素的后继 26 int ListInsert(sqlist &L, int i, int e); //插入操作 27 int ListDelete(sqlist &L, int i, int *e); //删除操作 28 void TravelList(sqlist L); //便历操作 29 #endif
4;顺序表结构体示意图
5;InitList函数实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include"defs.h" 2 3 void InitList(sqlist *L) 4 { 5 L->elem = (int *)malloc(LIST_INIT_MAX*sizeof(int)); //初始化指针 6 if (!L->elem) 7 exit(-1); 8 L->length = 0; //初始化当前元素个数 9 L->listsize = LIST_INIT_MAX; //初始化表长 10 }
6;DestroyList函数实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include"defs.h" 2 3 void DestroyList(sqlist *L) 4 { 5 free(L->elem); //释放空间 6 L->elem = NULL; //将指针置空 7 L->length = 0; //当前元素个数为0 8 L->listsize = 0; //表长为0 9 }
7;ClearList函数实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include"defs.h" 2 3 void ClearList(sqlist *L) 4 { 5 L->length = 0; //令当前元素个数为0 6 }
8;ListEmpty函数实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include"defs.h" 2 3 void ListEmpty(sqlist L) 4 { 5 if (L.length == 0) 6 printf("表为空.\n"); 7 else 8 printf("表不为空.\n"); 9 }
9;ListLength函数实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include"defs.h" 2 3 int ListLength(sqlist L) 4 { 5 return L.length; //返回表的当前元素个数 6 }
10;GetElem函数实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include"defs.h" 2 3 int GetElem(sqlist L, int i, int *e) //1<= i <=L.length 4 { 5 if (i<1 || i>L.length) 6 { 7 printf("取值位置不正确。\n"); 8 return 0; 9 } 10 *e = *(L.elem + i - 1); 11 return 0; 12 }
11;LocateElem函数实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include"defs.h" 2 3 void LocateElem(sqlist L, int e) 4 { 5 int i; 6 int * p = L.elem; 7 8 for (i=0; i<L.length; i++, p++) 9 if (*p == e) 10 printf("找到值为%d的元素,其位置为%d\n", e, i+1); 11 12 printf("在顺序表中没有找到值为%d的元素.\n", e); 13 }
12;PriorElem函数实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 PriorElem.c 2 #include"defs.h" 3 4 int PriorElem(sqlist L, int cur_e, int *pri_e) //第一个元素无前驱 5 { 6 int i; 7 int *p = L.elem; 8 9 for (i=0; i<L.length; i++,p++) //顺序表长度已知,故用for循环 10 { 11 if (i==0 && *p==cur_e) 12 { 13 printf("当前元素为第一个元素,无前驱.\n"); 14 return 0; 15 } 16 if (*p == cur_e) //找到了当前元素且不是第一个元素, 17 { 18 *pri_e = *--p; //将其前驱赋给引用参数 19 return 0; 20 } 21 } 22 printf("顺序表中无当前值%d。\n", cur_e); 23 return 0; 24 }
13;NextElem函数实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 NextElem.c 2 #include"defs.h" 3 4 int NextElem(sqlist L, int cur_e, int *nex_e) //最后一个元素无后继 5 { 6 int i; 7 int *p = L.elem; 8 9 for (i=0; i<L.length; i++) //顺序表长度已知,故用for 10 { 11 if (i==L.length-1 || *p==cur_e) 12 { 13 printf("当前元素为最后一个元素,无后继.\n"); 14 return 0; 15 } 16 if (*p == cur_e) 17 { 18 *nex_e = *++p; //将后继赋给引用参数带回 19 return 0; 20 } 21 } 22 printf("顺序表中无当前值%d。\n", cur_e); 23 return 0; 24 }
14;ListInsert函数实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 ListInsert.c 2 #include"defs.h" 3 4 int ListInsert(sqlist *L, int i, int e) //1<= i <=L->length+1 5 { 6 int *newbase, *p, *q; 7 8 if (i<1 || i>L->length+1) //插入位置不合理 9 { 10 printf("插入位置不合理.\n"); 11 return 0; 12 } 13 if (L->length == L->listsize) //表已满 14 { 15 newbase = (int *)realloc(L->elem, (L->listsize + LIST_INCREMENT) * sizeof (int)); //用newbase指针是为了保护L->elem 16 if (!newbase) 17 { 18 printf("继续分配内存空间失败.\n"); 19 exit(-1); 20 } 21 L->listsize += LIST_INCREMENT; 22 } 23 p = L->elem + i - 1; //p指向插入的位置 24 q = L->elem + L->length - 1; //q指向表中元素最后一个位置 25 26 for (; q>=p; q--) //从最后一个元素开始依次向后移动表中元素 27 *(q+1) = *q; 28 *q = e; //插入元素 29 L->length++; // 表长增一 30 return 0; 31 }
15;ListDelete函数实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 ListDelete.c 2 3 #include"defs.h" 4 5 int ListDelete(sqlist *L, int i, int *e) //1<= i <=L->length 6 { 7 int *p, *q; 8 9 if (i<1 || i>L->length) 10 { 11 printf("删除位置不合理.\n"); 12 return 0; 13 } 14 15 p = L->elem + i - 1; //p指向要删除的元素的位置 16 q = L->elem + L->length - 1; //q指向表中最后一个元素位置 17 18 *e = *p; //将要删除的元素保存起来 19 for (; p<=q; p++) //从要删除元素的后面一个元素开始移动元素 20 *p = *(p+1); 21 L->length--; //表长减一 22 return 0; 23 }
16;TravelList函数实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 TravelList.c 2 3 #include "defs.h" 4 5 void TravelList(sqlist L) 6 { 7 int i 8 int *p = L.elem; 9 10 for (i=0; i<L.length; i++,p++) 11 { 12 printf("第%d个元素为:%d\n", i+1, *p); 13 } 14 15 }
17;makefile的实现
1 object = main.o InitList.o DestroyList.o ClearList.o ListEmpty.o \ 2 ListLength.o GetElem.o LocateElem.o PriorElem.o NextElem.o \ 3 ListInsert.o ListDelete.o TravelList.o 4 5 test : $(object) 6 gcc -g -Wall -o test $(object) 7 main.o : defs.h 8 InitList.o : defs.h 9 DestroyList.o : defs.h 10 ClearList.o : defs.h 11 ListEmpty.o : defs.h 12 ListLength.o : defs.h 13 GetElem.o : defs.h 14 LocateElem.o : defs.h 15 PriorElem.o : defs.h 16 NextElem.o : defs.h 17 ListInsert.o : defs.h 18 ListDelete.o : defs.h 19 TravelList.o : defs.h 20 21 .PHONY : clean 22 clean : 23 rm *.o -f
18;顺序表的优缺点:顺序表由于其存储结构的特点,特别适合查找(其时间复杂度为O(1)),不适合频繁插入和删除(每一次插入和删除的时间复杂度都是O(n))