顺序表中的思路
在c语言当中判断数组的长度是比较麻烦的,不像其他语言可以通过对象的属性或者方法来获得长度。
int arr[4]; int length = sizeof(arr)/sizeof(arr[0]); //数组占内存总空间,除以单个元素占内存空间大小
而有一种类似数组的数据结构叫线性表,可以用来很方便的获取数组的长度。其结构体为
typedef struct { int data[1024]; int last; } List;
该数据结构除了定义了一个长度为1024的数组外,还多定义一个变量last用于存储数组长度,
如果要使用这种数据类型完成基本的读写操作,那么:
定义该指针为:List * list;
写入数据则为:list->data[0] = 32;
读取长度则为:printf("The length is %d\n",list->last);
而对于这种 “自带长度的数组“ 数据结构有两个问题:
1.它是否能完成一些比较高级的操作呢?如:添加,插入,删除,读取。
2.如果可以完成,那它不就是动态数组了吗?因为添加,删除,插入是会改变数组的长度的。
首先说说第二个问题
事实上这种数据结构并非动态数组,因为在结构体里已经声明了1024个字节给这个数组,而变量last只是表示
当前有效存储值的长度,而不是这个数组的总长度,这个当前存储长度是不能超过这个最大长度1024个字节的。
也就是说无论你做添加,删除,或者插入,数组的总长度仍然是1024个字节。因此不是动态数组。
然后再来看第一个问题
数据结构的存在的意义在于其内部结构是否孕育出一个好的算法在其身上,好的算法让我们对这些数据所做的处理
在性能上占据优势。这个性能包括时间性能和空间性能。因此带着这个问题我们一起来看看这个数据结构,对了,忘记
介绍这个数据结构的名称了,它叫顺序表。
首先是初始化顺序表
List * createList(void){ List * list = (List*)malloc(sizeof(List)); list->last = 0; return list; }
然后下分析如何实现插入和删除操作:(在此献上自画的丑图)
如第一行所示,我们已经初始化了一个长度为5的顺序表,并为其附上值,而list->last表示当前存储长度,也就是5
第二行红色字体表示在下标为2的地方插入一个值(30)。这时候为了保留原有的值,因此从下标为2开始后面的值
都需要往后面挪一位,腾出空位来,另外必须按照a,b,c,d的顺序来挪动,因为你先把桥拆了怎么过河?最后list->last++
表示存储长度+1
第三行是对第二行进行删除操作,即对下标为2的值的删除操作,那么需要把后面2后面的数组往前挪动来覆盖其值
操作的顺序一样也需要按照图中注明的a,b,c来执行,最后让list->last--;
思路有了后,上代码:
插入操作
void insertList(List *list,int index,int value){ if(list->last >= MAX)exit(1);int i; for(i=list->last;i>index;i--) list->data[i] = list->data[i-1]; list->data[i] = value; list->last++; }
删除操作
void deleteList(List *list,int index){ if(index<0||index>list->last)exit(1);int i; for(i=index;i<list->last;i++) list->data[i] = list->data[i+1]; list->last--; }
追加操作
void appendList(List *list,int value){ if(list->last >= MAX)exit(1);
list->data[list->last] = value; list->last++; }
读取操作就直接 list->data[x] 长度也是 list->last;
然后分析一下时间性能:
对于插入和删除操作都需要大量元素挪动位置,并且随着存储元素的增加,挪动的次数也会增加,所以最坏的时间复杂度是O(n)
而插入和删除最好的情况就是对最后一个元素操作,那么不需要挪动其他元素,最好的时间复杂度为O(1)
因此插入和删除的平局时间复杂度为 O(1) + O(n) = O(n)
对于读取和追加,都不需要挪动其他元素的位置,因此时间复杂度为O(1)
顺序表的思路就说到这了,最后来点和顺序表有关的代码,如果觉得本文不错,欢迎转载本文,希望各位注明出处:
http://www.cnblogs.com/demonxian3/p/7096742.html
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define MAX 100 4 #define ERROR 0 5 #define OK 1 6 7 typedef struct{ 8 int data[MAX]; 9 int last; 10 } List; 11 12 13 List * createList(void){ 14 List * list = (List*)malloc(sizeof(List)); 15 list->last = 0; 16 return list; 17 } 18 19 void printList(List * list){ 20 21 if(list->last == 0)printf("list is empty\n"); 22 23 int i; 24 for(i=0;i<list->last;i++){ 25 printf("[%d] ",list->data[i]); 26 } 27 28 printf("\n"); 29 } 30 31 void appendList(List *list,int value){ 32 33 if(list->last >= MAX){ 34 printf("Sorry,list is overflow\n"); 35 exit(ERROR); 36 } 37 38 list->data[list->last] = value; 39 list->last++; 40 } 41 42 void insertList(List *list,int index,int value){ 43 44 if(list->last >= MAX){ 45 printf("Sorry,list is overflow\n"); 46 exit(ERROR); 47 } 48 49 int i; 50 for(i=list->last;i>index;i--) 51 list->data[i] = list->data[i-1]; 52 53 list->data[i] = value; 54 list->last++; 55 } 56 57 void deleteList(List *list,int index){ 58 if(index<0||index>list->last){ 59 printf("invalid index\n"); 60 exit(ERROR); 61 } 62 63 int i; 64 for(i=index;i<list->last;i++) 65 list->data[i] = list->data[i+1]; 66 67 list->last--; 68 } 69 70 int main(){ 71 int index,value; 72 List * list = createList(); 73 74 //append 75 printf("[append] enter the value:"); 76 scanf("%d",&value); 77 appendList(list,value); 78 printList(list); 79 80 //append 81 printf("[append] enter the value:"); 82 scanf("%d",&value); 83 appendList(list,value); 84 printList(list); 85 86 //insert 87 printf("[insert] enter the index:"); 88 scanf("%d",&index); 89 printf("[insert] enter the value:"); 90 scanf("%d",&value); 91 insertList(list,index,value); 92 printList(list); 93 94 //delete 95 printf("[delete] enter the index:"); 96 scanf("%d",&index); 97 deleteList(list,index); 98 printList(list); 99 100 return OK; 101 }
Link.code