02_线性表
一、描述线性表
在一个非空有限的集合中,存在唯一一个被称为“第一个”的数据元素,和唯一一个被称为“最后一个”的数据元素,除第一个之外,每个元素只有一个直接前驱,除最后一个外,每个元素只有一个直接后驱。
二、线性表基本运算
构造一个空线性表、判断是否为空、返回线性表中元素的个数,返回线性表中索引 i 的数据元素,排序,拆分,清空,销毁等
三、线性表顺序存储
1 #include <stdio.h> 2 #include <malloc.h> 3 #include <stdlib.h> 4 5 6 //定义一个数据类型 Array 来模拟数组 7 struct Array 8 { 9 int *pBase;// 数组的首地址 10 int len;//数组的长度 11 int count;//数组元素个数 12 }; 13 14 void initArr(struct Array *pArr,int length); 15 void showArray(struct Array *pArr); 16 bool arr_Isempty(struct Array *pArr); 17 bool arr_full(struct Array* pArr); 18 //插入元素 19 bool append_arr(struct Array* pArr,int val); 20 bool insert_arr(struct Array* pArr,int pos,int val); 21 bool delete_arr(struct Array *pArr,int pos); 22 void inversion_arr(struct Array* pArr); 23 int main(void) 24 { 25 //定义一个结构体变量 26 struct Array arr; 27 //初始化 28 initArr(&arr,6); 29 //打印数组元素 30 //showArray(&arr); 31 //传入数组元素 32 append_arr(&arr,1); 33 append_arr(&arr,2); 34 append_arr(&arr,3); 35 append_arr(&arr,4); 36 append_arr(&arr,5); 37 // append_arr(&arr,6); 38 39 insert_arr(&arr,2,88); //1 88 2 3 4 5 40 delete_arr(&arr,2); 41 showArray(&arr); 42 printf("\n倒置:\n"); 43 inversion_arr(&arr); 44 showArray(&arr); 45 } 46 47 //初始化数组,分配空间,指定长度和元素总个数 48 void initArr(struct Array *pArr,int length) 49 { 50 pArr->pBase = (int *)malloc(sizeof(struct Array) * length); 51 if(pArr->pBase == NULL) 52 { 53 printf("内存分配失败!"); 54 return; 55 } 56 else 57 { 58 pArr->len = length; 59 pArr->count = 0; 60 } 61 return ; 62 } 63 //判断数组是否为空 64 bool arr_Isempty(struct Array *pArr) 65 { 66 //如果数组总个数为空,返回true 67 if(0 == pArr->count) 68 { 69 return true; 70 } 71 else 72 { 73 return false; 74 } 75 } 76 bool arr_full(struct Array* pArr) 77 { 78 if(pArr->count == pArr->len) 79 { 80 printf("已满\n"); 81 return true; 82 } 83 else 84 { 85 return false; 86 } 87 } 88 //循环打印数组 89 void showArray(struct Array *pArr) 90 { 91 //首先判断数组元素是否为空 92 if(arr_Isempty(pArr)) 93 { 94 printf("数组元素为空!"); 95 return; 96 } 97 else 98 { 99 //循环打印输出 100 for(int i = 0;i < pArr->count;i++) 101 { 102 printf("%d ",pArr->pBase[i]); 103 } 104 } 105 106 } 107 108 bool append_arr(struct Array* pArr,int val) 109 { 110 //判断数组是否已满 111 if (arr_full(pArr)) 112 { 113 printf("数组已满,插入失败!"); 114 return false; 115 } 116 pArr->pBase[pArr->count] = val; 117 pArr->count++; 118 } 119 //插入元素 120 bool insert_arr(struct Array* pArr,int pos,int val) 121 { 122 if(arr_full(pArr)){ 123 return false; 124 } 125 if(pos < 1 || pos > pArr->count + 1){ 126 return false; 127 } 128 129 int i ; 130 for (i=pArr->count-1;i >= pos - 1; --i) 131 { 132 pArr->pBase[i+1] = pArr->pBase[i]; 133 } 134 pArr->pBase[pos-1] = val; 135 pArr->count++; 136 return true; 137 } 138 // 1 88 2 3 4 5 2 139 bool delete_arr(struct Array *pArr,int pos) 140 { 141 if(arr_Isempty(pArr)) 142 { 143 printf("数组为空,删除元素失败!"); 144 return false; 145 } 146 if(pos > pArr->count || pos < 1) 147 { 148 printf("范围错误!"); 149 return false; 150 } 151 int i; 152 for(i = pos;i < pArr->count;i++) 153 { 154 //printf("\n pArr->pBase[i] : %d\n",pArr->pBase[i]); 155 pArr->pBase[i-1] = pArr->pBase[i]; 156 } 157 pArr->count -- ; 158 return true; 159 } 160 161 void inversion_arr(struct Array* pArr) 162 { 163 int i = 0; 164 int j = pArr->count -1 ;//数组是从开始的 165 int t = 0; 166 while(i < j) 167 { 168 t = pArr->pBase[i]; 169 // printf("t : %d\n",t); 170 // printf("j : %d\n",j); 171 pArr->pBase[i] = pArr->pBase[j]; 172 pArr->pBase[j] = t; 173 // printf(" pBase[i] : %d\n",pArr->pBase[j]); 174 ++i; 175 --j; 176 } 177 } 178
四、线性表链式存储
1 #include<stdio.h> 2 #include<malloc.h> 3 #include<stdlib.h> 4 5 //定义了一个 数据类型 6 typedef struct Node 7 { 8 int data; //数据域 9 struct Node* pNext;//指针域 10 }NODE,* PNODE;//NODE == struct Node ; PNODE = struct Node* 11 12 PNODE create_list(void); 13 void traverse_list(PNODE pHead); 14 bool isempty_list(PNODE pHead); 15 int length_list(PNODE pHead); 16 bool insert_list(PNODE pHead,int pos,int val); 17 bool delete_list(PNODE pHead,int pos,int *val); 18 void sort_list(PNODE pHead); 19 20 int main(void) 21 { 22 int val; 23 PNODE pHead = NULL;//struct Node* pHead 指向Node的指针变量 24 pHead = create_list();//创建一个非循环单链表,单链表头节点地址返回给pHead 25 traverse_list(pHead); 26 /* if(isempty_list(pHead)) 27 { 28 printf("链表为空!\n"); 29 }else 30 { 31 printf("链表不为空!\n"); 32 } 33 */ 34 printf("链表的长度:%d.\n",length_list(pHead)); 35 //insert_list(pHead,1,5); 在首结点前插入 36 // insert_list(pHead,5,5); 当要插入的结点大于总长度的时候 37 // printf("插入元素后:\n"); 38 // traverse_list(pHead); 39 // printf("删除元素后:\n"); 40 // delete_list(pHead,1,&val); 41 // printf("被删除的元素为:%d\n",val); 42 //traverse_list(pHead); 43 sort_list(pHead); 44 traverse_list(pHead); 45 return 0; 46 } 47 48 //创建一个链表 49 PNODE create_list(void) 50 { 51 int len;//链表的长度 52 int i; 53 int val;//临时存储数据 54 printf("请输入你需要的链表长度len =\n") ; 55 scanf("%d",&len); 56 PNODE pHead = (PNODE)malloc(sizeof(NODE)); 57 if(NULL == pHead) 58 { 59 printf("内存分配失败!"); 60 exit(-1); 61 } 62 63 PNODE pTail = pHead; 64 pTail->pNext = NULL; 65 for(i = 0;i < len;i++) 66 { 67 printf("请输入要存储的数据:\n"); 68 scanf("%d",&val); 69 //创建一个个链表 70 PNODE pNew = (PNODE)malloc(sizeof(NODE)); 71 if(NULL == pNew) 72 { 73 printf("pNew内存分配失败!"); 74 exit(-1); 75 } 76 pNew->data = val; 77 78 pTail->pNext = pNew;//把新结点挂在尾结点的后面 79 pNew->pNext = NULL;//新结点变成尾结点了 80 pTail = pNew;//然后pTail指向新结点变成尾结点 81 } 82 83 return pHead; 84 } 85 86 //遍历链表 87 void traverse_list(PNODE pHead) 88 { 89 PNODE p = pHead->pNext; // 让p指向首结点 90 while(NULL != p) 91 { 92 printf("%d\t",p->data); 93 p = p->pNext; //p往后移 94 } 95 printf("\n"); 96 return; 97 } 98 bool isempty_list(PNODE pHead) 99 { 100 if(NULL == pHead || pHead->pNext == NULL) 101 { 102 return true; 103 } 104 else 105 { 106 return false; 107 } 108 } 109 110 int length_list(PNODE pHead) 111 { 112 int i = 0; 113 PNODE p = pHead->pNext; 114 while (p != NULL) 115 { 116 i++; 117 p = p->pNext; 118 } 119 return i; 120 } 121 122 //插入 123 bool insert_list(PNODE pHead,int pos,int val) 124 { 125 int i ; 126 PNODE pT = pHead; 127 PNODE pTmp = (PNODE)malloc(sizeof(NODE)); 128 PNODE pNew = (PNODE)malloc(sizeof(NODE)); 129 pNew->data = val; 130 131 if(pos == 1) 132 { 133 for(i = 0;i < pos-1;i++) 134 { 135 pTmp = pT->pNext;//第一个结点 136 pNew = pTmp->pNext; 137 pTmp->pNext = pNew; 138 } 139 } 140 else if(pos > length_list(pHead)) 141 { 142 for(i = 0;i < length_list(pHead) ;i++){ 143 pT = pT->pNext; 144 } 145 pNew->pNext = pT->pNext; 146 pT->pNext = pNew; 147 } 148 else 149 { 150 for(i = 0;i < pos -1;i++) 151 { 152 pT = pT->pNext; 153 } 154 155 pNew->pNext = pT->pNext; 156 pT->pNext = pNew; 157 } 158 159 160 return true; 161 } 162 //删除元素 163 bool delete_list(PNODE pHead,int pos,int *val) 164 { 165 int i; 166 if(pos < 1 || pos > length_list(pHead)) 167 { 168 printf("\n位置超出范围,删除失败!\n"); 169 exit(-1); 170 } 171 PNODE pNode = (PNODE)malloc(sizeof(NODE)); 172 PNODE pTmp = pHead; 173 //printf("\n pos : %d",pos); 174 for(i = 0;i < pos -1;i++) 175 { 176 pTmp = pTmp->pNext;//此时pTmp指向的是首结点 177 pNode = pTmp->pNext;//此时pTmp指向的是第二个结点,赋给pNode,pNode指向的就是第二个结点 178 pTmp->pNext = pNode->pNext;//此时获取到的是第三个结点,赋给了pTmp,pTmp指向了第三个结点 179 *val = pNode->data; 180 printf("\n第%d结点的元素是%d.\n",pos,pNode->data); 181 free(pNode); 182 } 183 } 184 185 void sort_list(PNODE pHead) 186 { 187 //从狭义的讲 算法和存储结构有关 188 //广义讲 算法和存储结构无关 189 int i,j,t; 190 PNODE p,q; 191 int len = length_list(pHead); 192 for(i = 0,p = pHead->pNext;i < len -1;i++,p = p->pNext) 193 { 194 for(j = i+1,q = p->pNext;j < len;j++ ,q=q->pNext) 195 { 196 if(p->data > q->data)//类似数组中的 a[i] > a[j] 197 { 198 t = p->data;//类似数组中的 t= a[i] 199 p->data = q->data;//类似数组中的 a[i]= a[j] 200 q->data = t;//类似数组中的 a[j]= t 201 } 202 } 203 } 204 }
五、顺序表和链表的比较
1.如果线性表需要频繁查找,很少进行插入和删除,宜采用顺序表结构,反之,采用链表
2.线性表个数不能确定的情况下,链表优于顺序表。