线性表 —— 顺序存储
线性表的顺序存储:
线性表顺序存储结构的定义:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define MAXSIZE 100 4 typedef int ElemType; /*给int类型定义一个别名*/ 5 typedef struct { 6 ElemType elem[MAXSIZE];/*线性表占用的数组空间*/ 7 int last;/*记录线性表中最后一个元素在数组中elem[]中的位置(下标值),空表置为-1*/ 8 }Seqlist;
顺序表的初始化:
1 Seqlist* InitList() { 2 /* 将SeqList大小的数据动态的分配给指针*L,(SeqList*)强制转换成指针类型*/ 3 Seqlist* L = (Seqlist*)malloc(sizeof(Seqlist)); 4 L->last = -1; 5 return L; 6 } 7 void main() { 8 /*初始化线性表返回的是指针类型,所以主函数中要定义一个指针类型接收*/ 9 Seqlist* L = InitList(); 10 }
顺序表中添加元素:
1 void addList(SeqList* L, ElemType e) { 2 L->last++; 3 L->elem[L->last] = e; 4 }
顺序表中元素的打印:
1 void printfList(SeqList* L) { 2 for (int i = 0; i <=L->last; i++) 3 { 4 printf("%d ", L->elem[i]); 5 } 6 printf("\n"); 7 } 8 int main(){ 9 ElemType e; 10 /*初始化线性表返回的是指针类型,所以主函数中要定义一个指针类型接收*/ 11 SeqList* L = InitList(); 12 13 printf("原始数据:"); 14 /*若调用一次该函数,L->last+1(L->last=-1变为L->last=0),并向L->last=0的地址中添加数据e=10*/ 15 addList(L, 10); 16 /*若调用第二次该函数,L->last+1(L->last=0变为L->last=1),并向L->last=1的地址中添加数据e=20*/ 17 addList(L, 20); 18 addList(L, 30); 19 addList(L, 40); 20 /*打印线性表中的元素*/ 21 printfList(L); 22 }
顺序表中插入运算,第i元素位置前插入元素e:
1 /*在线性表L中第i个元素之前插入一个元素e。i(1<=i<=last+2)*/ 2 int InsList(SeqList* L, int i, ElemType e) { 3 int k; 4 /* 5 当元素i小于线性表中的第一个元素时,不能在第一个元素之前插入 6 或线性表中有4个元素,最后一个元素的地址L->last=3。 7 L->last+2=5,若i>5,不能插入;若插入造成不连续性,不属于线性表了 8 */ 9 if (i<1 || i>L->last + 2) 10 { 11 printf("插入位置i值不合法"); 12 return ERROR; 13 } 14 /* 15 若L->last=99,游标为99的属于线性表中的最后一个元素。 16 插入一个元素,在其后的元素后移,造成存储大小不够,线性表的存储范围(0~99) 17 */ 18 if (L->last >= MAXSIZE - 1) 19 { 20 printf("表已满,无法插入"); 21 return ERROR; 22 } 23 /* 24 L->last=3; k>=i-1,i=2,所以k>=1 25 */ 26 for (k = L->last; k >= i - 1; k--) 27 { 28 /* 29 * 循环一次将L->elem[3]的元素赋值给L->elem[4],即元素后移 30 * 循环第二次k-1=2,将L->elem[2]的元素赋值给L->elem[3] 31 * 循环第三次k-1=1,将L->elem[1]的元素赋值给L->elem[2] 32 * 循环结束k-1=0,结束循环 33 */ 34 L->elem[k + 1] = L->elem[k]; 35 } 36 /*因为L->elem[1]的元素后移到L->elem[2],L->elem[1]的位置就空出来了,可以向其添加数据*/ 37 L->elem[i - 1] = e; /*第i个元素的下标为i-1*/ 38 /*因为增加了一个元素,所以游标跟着变化由L->last=3变为L->last=4*/ 39 L->last++; 40 return OK; 41 } 42 int main() { 43 ElemType e; 44 /*初始化线性表返回的是指针类型,所以主函数中要定义一个指针类型接收*/ 45 SeqList* L = InitList(); 46 47 printf("原始数据:"); 48 /*若调用一次该函数,L->last+1(L->last=-1变为L->last=0),并向L->last=0的地址中添加数据e=10*/ 49 addList(L, 10); 50 /*若调用第二次该函数,L->last+1(L->last=0变为L->last=1),并向L->last=1的地址中添加数据e=20*/ 51 addList(L, 20); 52 addList(L, 30); 53 addList(L, 40); 54 /*打印线性表中的元素*/ 55 printfList(L); 56 57 printf("添加数据:"); 58 InsList(L, 2, 100); 59 printfList(L); 60 return 0; 61 }
顺序表的删除运算,删除第i个数据元素:
1 /*在顺序表L中删除第i个数据元素。i(1<=i<=L->last+1)*/ 2 int DelList(SeqList* L, int i, ElemType* e) { 3 int k; 4 if (i<1 || i>L->last + 1) { 5 printf("删除位置不合法!"); 6 return ERROR; 7 } 8 *e = L->elem[i - 1]; /*将删除的元素存放到e所指向的变量中*/ 9 /*k=2;L->last=4;k<=4*/ 10 for (k = i; k <= L->last; k++) 11 { 12 /*后面元素向前移动和添加一个元素类似*/ 13 L->elem[k - 1] = L->elem[k]; 14 } 15 /*删除一个元素游标减1*/ 16 L->last--; 17 return OK; 18 } 19 int main() { 20 ElemType e; 21 /*初始化线性表返回的是指针类型,所以主函数中要定义一个指针类型接收*/ 22 SeqList* L = InitList(); 23 24 printf("原始数据:"); 25 /*若调用一次该函数,L->last+1(L->last=-1变为L->last=0),并向L->last=0的地址中添加数据e=10*/ 26 addList(L, 10); 27 /*若调用第二次该函数,L->last+1(L->last=0变为L->last=1),并向L->last=1的地址中添加数据e=20*/ 28 addList(L, 20); 29 addList(L, 30); 30 addList(L, 40); 31 /*打印线性表中的元素*/ 32 printfList(L); 33 34 printf("添加数据:"); 35 InsList(L, 2, 100); 36 printfList(L); 37 38 printf("删除数据:"); 39 DelList(L, 2, &e); 40 printfList(L); 41 return 0; 42 }
顺序表的按内容查找运算,查找与e相等的元素:
1 /* 在顺序表L中查找与e相等的元素,若L->elem[i]=e,则找到该元素,并返回元素的下标i,若找不到返回-1*/ 2 int Locate(SeqList* L, ElemType e) { 3 int i = 0; 4 while (i <= L->last && L->elem[i] != e) 5 { 6 i++; 7 } 8 if (i <= L->last) 9 { 10 return (i); 11 } 12 else 13 { 14 return (-1); 15 } 16 } 17 int main() { 18 ElemType e; 19 /*初始化线性表返回的是指针类型,所以主函数中要定义一个指针类型接收*/ 20 SeqList* L = InitList(); 21 22 printf("原始数据:"); 23 /*若调用一次该函数,L->last+1(L->last=-1变为L->last=0),并向L->last=0的地址中添加数据e=10*/ 24 addList(L, 10); 25 /*若调用第二次该函数,L->last+1(L->last=0变为L->last=1),并向L->last=1的地址中添加数据e=20*/ 26 addList(L, 20); 27 addList(L, 30); 28 addList(L, 40); 29 /*打印线性表中的元素*/ 30 printfList(L); 31 32 printf("添加数据:"); 33 InsList(L, 2, 100); 34 printfList(L); 35 36 printf("删除数据:"); 37 DelList(L, 2, &e); 38 printfList(L); 39 40 printf("查找数据的位置:"); 41 int n = Locate(L, 20); 42 if (n<0) 43 { 44 printf("没找到"); 45 } 46 else { 47 printf("%d ",n + 1); 48 printf("查找的数:%d\n", L->elem[n]); 49 } 50 return 0; 51 }
顺序表中插入一个元素e,插入元素后,保障顺序表还是有序:
1 /*插入一个元素,保障线性表的有序性*/ 2 int InsOrderList(SeqList* L, ElemType e) { 3 int i; 4 for (i = L->last;i >= 0;i--) { 5 if (L->elem[i]>e) { 6 L->elem[i + 1] = L->elem[i]; 7 } 8 else { 9 break; 10 } 11 } 12 L->elem[i + 1] = e; 13 L->last++; 14 return OK; 15 } 16 int main() { 17 ElemType e; 18 /*初始化线性表返回的是指针类型,所以主函数中要定义一个指针类型接收*/ 19 SeqList* L = InitList(); 20 21 printf("原始数据:"); 22 /*若调用一次该函数,L->last+1(L->last=-1变为L->last=0),并向L->last=0的地址中添加数据e=10*/ 23 addList(L, 10); 24 /*若调用第二次该函数,L->last+1(L->last=0变为L->last=1),并向L->last=1的地址中添加数据e=20*/ 25 addList(L, 20); 26 addList(L, 30); 27 addList(L, 40); 28 /*打印线性表中的元素*/ 29 printfList(L); 30 31 printf("添加数据:"); 32 InsList(L, 2, 100); 33 printfList(L); 34 35 printf("删除数据:"); 36 DelList(L, 2, &e); 37 printfList(L); 38 39 printf("查找数据的位置:"); 40 int n = Locate(L, 20); 41 if (n<0) 42 { 43 printf("没找到"); 44 } 45 else { 46 printf("%d ",n + 1); 47 printf("查找的数:%d\n", L->elem[n]); 48 } 49 50 printf("按顺序插入元素:"); 51 InsOrderList(L,150); 52 printfList(L); 53 54 return 0; 55 }
顺序表操作总代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define MAXSIZE 100 4 #define OK 1 5 #define ERROR 0 6 typedef int ElemType; 7 typedef struct { 8 ElemType elem[MAXSIZE]; 9 int last; 10 }SeqList; 11 /*初始化线性列表*/ 12 SeqList* InitList() { 13 /* 将SeqList大小的数据动态的分配给指针*L (SeqList*)强制转换成指针类型 */ 14 SeqList* L = (SeqList*)malloc(sizeof(SeqList)); 15 L->last = -1; 16 return L; 17 } 18 /*向线性列表中添加数据*/ 19 void addList(SeqList* L, ElemType e) { 20 L->last++; 21 L->elem[L->last] = e; 22 } 23 /*打印线性列表中的数据*/ 24 void printfList(SeqList* L) { 25 for (int i = 0; i <= L->last; i++) 26 { 27 printf("%d ", L->elem[i]); 28 } 29 printf("\n"); 30 } 31 /*在线性表L中第i个元素之前插入一个元素e。i(1<=i<=last+2)*/ 32 int InsList(SeqList* L, int i, ElemType e) { 33 int k; 34 /* 35 当元素i小于线性表中的第一个元素时,不能在第一个元素之前插入 36 或线性表中有4个元素,最后一个元素的地址L->last=3。 37 L->last+2=5,若i>5,不能插入;若插入造成不连续性,不属于线性表了 38 */ 39 if (i<1 || i>L->last + 2) 40 { 41 printf("插入位置:值不合法"); 42 return ERROR; 43 } 44 /* 45 若L->last=99,游标为99的属于线性表中的最后一个元素。 46 插入一个元素,在其后的元素后移,造成存储大小不够,线性表的存储范围(0~99) 47 */ 48 if (L->last >= MAXSIZE - 1) 49 { 50 printf("表已满,无法插入"); 51 return ERROR; 52 } 53 /* 54 L->last=3; k>=i-1,i=2,所以k>=1 55 */ 56 for (k = L->last; k >= i - 1; k--) 57 { 58 /* 59 * 循环一次将L->elem[3]的元素赋值给L->elem[4],即元素后移 60 * 循环第二次k-1=2,将L->elem[2]的元素赋值给L->elem[3] 61 * 循环第三次k-1=1,将L->elem[1]的元素赋值给L->elem[2] 62 * 循环结束k-1=0,结束循环 63 */ 64 L->elem[k + 1] = L->elem[k]; 65 } 66 /*因为L->elem[1]的元素后移到L->elem[2],L->elem[1]的位置就空出来了,可以向其添加数据*/ 67 L->elem[i - 1] = e; 68 /*因为增加了一个元素,所以游标跟着变化由L->last=3变为L->last=4*/ 69 L->last++; 70 return OK; 71 } 72 /*插入一个元素,保障线性表的有序性*/ 73 int InsOrderList(SeqList* L, ElemType e) { 74 int i; 75 for (i = L->last;i >= 0;i--) { 76 if (L->elem[i]>e) { 77 L->elem[i + 1] = L->elem[i]; 78 } 79 else { 80 break; 81 } 82 } 83 L->elem[i + 1] = e; 84 L->last++; 85 return OK; 86 } 87 /*在顺序表L中删除第i个数据元素。i(1<=i<=L.last+1)*/ 88 int DelList(SeqList* L, int i, ElemType* e) { 89 int k; 90 if (i<1 || i>L->last + 1) { 91 printf("删除位置不合法!"); 92 return ERROR; 93 } 94 *e = L->elem[i - 1]; 95 /*k=2;L->last=4;k<=4*/ 96 for (k = i; k <= L->last; k++) 97 { 98 /*后面元素向前移动和添加一个元素类似*/ 99 L->elem[k - 1] = L->elem[k]; 100 } 101 /*删除一个元素游标减1*/ 102 L->last--; 103 return OK; 104 } 105 /* 在顺序表L中查找与e相等的元素,若L.elem[i]=e,则找到该元素,并返回i+1,若找不到返回-1*/ 106 int Locate(SeqList* L, ElemType e) { 107 int i = 0; 108 while (i <= L->last && L->elem[i] != e) 109 { 110 i++; 111 } 112 if (i <= L->last) 113 { 114 return (i); 115 } 116 else 117 { 118 return (-1); 119 } 120 } 121 122 /*在顺序表L中查找与e相等的元素,若L.elem[i]=e*/ 123 int main() { 124 ElemType e; 125 /*初始化线性表返回的是指针类型,所以主函数中要定义一个指针类型接收*/ 126 SeqList* L = InitList(); 127 128 printf("原始数据:"); 129 /*若调用一次该函数,L->last+1(L->last=-1变为L->last=0),并向L->last=0的地址中添加数据e=10*/ 130 addList(L, 10); 131 /*若调用第二次该函数,L->last+1(L->last=0变为L->last=1),并向L->last=1的地址中添加数据e=20*/ 132 addList(L, 20); 133 addList(L, 30); 134 addList(L, 40); 135 /*打印线性表中的元素*/ 136 printfList(L); 137 138 printf("添加数据:"); 139 InsList(L, 2, 100); 140 printfList(L); 141 142 printf("删除数据:"); 143 DelList(L, 2, &e); 144 printfList(L); 145 146 printf("查找数据的位置:"); 147 int n = Locate(L, 20); 148 if (n<0) 149 { 150 printf("没找到"); 151 } 152 else { 153 printf("%d ",n + 1); 154 printf("查找的数:%d\n", L->elem[n]); 155 } 156 157 printf("按顺序插入元素:"); 158 InsOrderList(L,150); 159 printfList(L); 160 161 162 return 0; 163 }
线性表的合并运算:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define MAXSIZE 100 4 #define OK 1 5 #define ERROR 0 6 typedef int ElemTyle; 7 typedef struct { 8 ElemTyle elem[MAXSIZE]; 9 int last; 10 }SeqList; 11 /*初始化线性表*/ 12 SeqList* InitList() { 13 SeqList* L = (SeqList*)malloc(sizeof(SeqList)); 14 L->last = -1; 15 return L; 16 } 17 /*向线性表中添加元素*/ 18 void addList(SeqList* L, ElemTyle e) { 19 L->last++; 20 L->elem[L->last] = e; 21 } 22 /*打印线性表中的元素*/ 23 void printfList(SeqList* L) { 24 for (int i = 0; i <= L->last; i++) 25 { 26 printf("%d ", L->elem[i]); 27 } 28 printf("\n"); 29 } 30 /*合并线性表*/ 31 int margeList(SeqList* LA, SeqList* LB, SeqList* LC) { 32 int i, j, k; 33 i = 0;j = 0;k = 0; 34 while (i<=LA->last&&j<=LB->last) 35 { 36 if (LA->elem[i]<=LB->elem[j]) 37 { 38 LC->elem[k] = LA->elem[i]; 39 i++;k++; 40 } 41 else 42 { 43 LC->elem[k] = LB->elem[j]; 44 j++;k++; 45 } 46 } 47 while (i<=LA->last) 48 { 49 LC->elem[k] = LA->elem[i]; 50 i++;k++; 51 } 52 while (j<=LB->last) 53 { 54 LC->elem[k] = LB->elem[j]; 55 j++;k++; 56 } 57 LC->last = LA->last + LB->last + 1; 58 return OK; 59 } 60 int main() { 61 SeqList* LA = InitList(); 62 addList(LA, 2); 63 addList(LA, 4); 64 addList(LA, 6); 65 addList(LA, 8); 66 printf("线性表LA的元素:"); 67 printfList(LA); 68 69 SeqList* LB = InitList(); 70 addList(LB, 1); 71 addList(LB, 3); 72 addList(LB, 5); 73 addList(LB, 7); 74 addList(LB, 9); 75 printf("线性表LB的元素:"); 76 printfList(LB); 77 78 SeqList* LC = InitList(); 79 80 /*合并线性表*/ 81 printf("线性表LC的元素:"); 82 margeList(LA, LB, LC); 83 printfList(LC); 84 return 0; 85 }
顺序表的优点:
(1)无需为表示结点间的逻辑关系而增加额外的存储空间(因逻辑上相邻的元素其存储的物理位置也相邻)
(2)可以方便地随机存取表中的任一元素
顺序表的缺点:
(2)由于顺序表要求占用连续的存储空间,存储分配只能预先进行静态分配。当表长变得比较大时,难以确定合适的存储规模。