顺序线性表——实验及提升训练
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include<stdbool.h> 4 /*此处是顺序线性表数据结构定义*/ 5 typedef int DataType; 6 struct seqList 7 {//有3个数据成员 8 int MAXNUM;//用于记录顺序线性表中能存放的最大元素个数的 整型 MAXNUM 9 int curNum;//用于存放顺序线性表中数据元素的个数 整型 curNum 10 DataType *element;//用于存放顺序线性表数据元素的连续空间的起始地址 11 }; 12 13 typedef struct seqList *PseqList; 14 int binarySearch(PseqList plist,int target, int *pos, bool lower); 15 void searchRange(PseqList plist,int target, int *pos); 16 /*创建空的顺序线性表,能存放的最大元素个数为 m*/ 17 PseqList createNullList_seq(int m) 18 { //若m=0,则返回NULL 19 PseqList plist = (struct seqList *)malloc(sizeof(struct seqList)); 20 if(plist == NULL) return NULL; //分配空间失败 21 plist->MAXNUM = m ; 22 plist->curNum = 0; 23 plist->element = (DataType *)malloc(sizeof(DataType)*m); 24 if(plist->element == NULL) 25 { 26 free(plist); 27 return NULL; 28 } 29 return plist; 30 } 31 32 33 34 /*在线性表表尾插入数据元素,返回值0表示插入失败,返回值1表示在表尾插入成功*/ 35 int insertP_tail(PseqList plist , int x) 36 { 37 if(plist->curNum == plist->MAXNUM) //若表满,则无法插入 38 { 39 printf("list if full !"); 40 return 0; 41 } 42 plist->element[plist->curNum] = x ; 43 plist->curNum++; 44 return 1; 45 46 } 47 48 /*回收线性表占用的空间*/ 49 int destroyList_seq(PseqList plist) 50 { 51 //返回值为销毁的线性表中现有数据元素的个数,若待销毁的线性表不存在,则返回0 52 if(plist == NULL) return 0; 53 int m = plist->curNum; 54 free(plist->element); 55 free(plist); 56 return m; 57 58 } 59 60 void printList_seq(PseqList plist) 61 {//逐个输出线性表的元素,相邻的两个数据元素之间以一个空格为分隔符隔开 62 for(int i=0;i<plist->curNum;i++) 63 printf("%d ",plist->element[i]); 64 } 65 66 //第一关:求顺序线性表中连续子表(最少有一个元素)的最大和并输出 67 int seqMaxSum(PseqList plist) 68 { if (plist==NULL)return 0; 69 int curSum=plist->element[0]; 70 int max=plist->element[0]; 71 for (int i = 1; i < plist->curNum; ++i) { 72 if (curSum < 0) 73 { 74 curSum=plist->element[i]; 75 }else 76 { 77 curSum += plist->element[i]; 78 } 79 if (curSum > max) 80 { 81 max=curSum; 82 } 83 } 84 return max; 85 86 } 87 88 //第二关:寻找线性表中没有出现的最小的正整数 89 int findMinNumber(PseqList plist) 90 { 91 //若线性表为空,则返回0 92 if (plist==NULL)return 0; 93 for (int i = 0; i < plist->curNum; ++i) { 94 if (plist->element[i] <= 0) 95 { 96 plist->element[i] = plist->curNum + 1; 97 } 98 } 99 for (int i = 0; i < plist->curNum; ++i) { 100 int num = abs(plist->element[i]); 101 if (num <= plist->curNum) 102 { 103 plist->element[num - 1] = -abs(plist->element[num - 1]); 104 } 105 } 106 for (int i = 0; i < plist->curNum; ++i) { 107 if (plist->element[i] > 0) 108 { 109 return i + 1; 110 } 111 112 } 113 return plist->curNum + 1; 114 } 115 116 //第三关:找出给定目标值target在有序线性表中出现的起始位置和结束位置 117 void findPos(PseqList plist,int target, int *pos) 118 { 119 //起始位置放在pos[0], 结束位置放在pos[1] 120 searchRange( plist, target, pos); 121 122 } 123 124 125 126 127 int binarySearch(PseqList plist,int target, int *pos, bool lower) 128 { 129 int begin = 0; 130 int end = plist->curNum - 1; 131 int ans = plist->curNum; 132 while (begin <= end) 133 { 134 int mid = (begin+ end ) / 2; 135 if (plist->element[mid] > target || (lower && plist->element[mid] >= target)) 136 { 137 end = mid - 1; 138 ans = mid; 139 }else 140 { 141 begin = mid + 1; 142 } 143 } 144 return ans; 145 146 } 147 void searchRange(PseqList plist,int target, int *pos) 148 { 149 int leftIdx = binarySearch(plist,target,pos, true); 150 int rightIdx = binarySearch(plist,target,pos, false) - 1; 151 152 if (leftIdx <= rightIdx && rightIdx < plist->curNum && plist->element[leftIdx] == target && plist->element[rightIdx] == target) { 153 pos[0] = leftIdx, pos[1] = rightIdx; 154 return; 155 } 156 pos[0] = -1, pos[1] = -1; 157 158 } 159 160 161
1 // 2 // Created by keyter on 2020/12/23. 3 // 4 5 #ifndef CONTINUOUSSUBTABLESFIND_SEQLIST_H 6 #define CONTINUOUSSUBTABLESFIND_SEQLIST_H 7 #include <stdio.h> 8 #include <stdlib.h> 9 10 /*此处是顺序线性表数据结构定义*/ 11 typedef int DataType; 12 struct seqList 13 {//有3个数据成员 14 int MAXNUM;//用于记录顺序线性表中能存放的最大元素个数的 整型 MAXNUM 15 int curNum;//用于存放顺序线性表中数据元素的个数 整型 curNum 16 DataType *element;//用于存放顺序线性表数据元素的连续空间的起始地址 17 }; 18 19 typedef struct seqList *PseqList; 20 int binarySearch(PseqList plist,int target, int *pos, bool lower); 21 void searchRange(PseqList plist,int target, int *pos); 22 /*创建空的顺序线性表,能存放的最大元素个数为 m*/ 23 PseqList createNullList_seq(int m) 24 { //若m=0,则返回NULL 25 PseqList plist = (struct seqList *)malloc(sizeof(struct seqList)); 26 if(plist == NULL) return NULL; //分配空间失败 27 plist->MAXNUM = m ; 28 plist->curNum = 0; 29 plist->element = (DataType *)malloc(sizeof(DataType)*m); 30 if(plist->element == NULL) 31 { 32 free(plist); 33 return NULL; 34 } 35 return plist; 36 } 37 38 39 40 /*在线性表表尾插入数据元素,返回值0表示插入失败,返回值1表示在表尾插入成功*/ 41 int insertP_tail(PseqList plist , int x) 42 { 43 if(plist->curNum == plist->MAXNUM) //若表满,则无法插入 44 { 45 printf("list if full !"); 46 return 0; 47 } 48 plist->element[plist->curNum] = x ; 49 plist->curNum++; 50 return 1; 51 52 } 53 54 /*回收线性表占用的空间*/ 55 int destroyList_seq(PseqList plist) 56 { 57 //返回值为销毁的线性表中现有数据元素的个数,若待销毁的线性表不存在,则返回0 58 if(plist == NULL) return 0; 59 int m = plist->curNum; 60 free(plist->element); 61 free(plist); 62 return m; 63 64 } 65 66 void printList_seq(PseqList plist) 67 {//逐个输出线性表的元素,相邻的两个数据元素之间以一个空格为分隔符隔开 68 for(int i=0;i<plist->curNum;i++) 69 printf("%d ",plist->element[i]); 70 } 71 72 //第一关:求顺序线性表中连续子表(最少有一个元素)的最大和并输出 73 int seqMaxSum(PseqList plist) 74 { 75 if (plist==NULL)return 0; 76 int curSum=plist->element[0]; 77 int max=plist->element[0]; 78 for (int i = 1; i < plist->curNum; ++i) { 79 if (curSum < 0) 80 { 81 curSum=plist->element[i]; 82 }else 83 { 84 curSum += plist->element[i]; 85 } 86 if (curSum > max) 87 { 88 max=curSum; 89 } 90 } 91 return max; 92 } 93 94 //第二关:寻找线性表中没有出现的最小的正整数 95 int findMinNumber(PseqList plist) 96 {//hashTable 97 /*对于「前言」中提到的第一种做法: 98 99 我们可以将数组所有的数放入哈希表,随后从 11 开始依次枚举正整数,并判断其是否在哈希表中。 100 101 仔细想一想,我们为什么要使用哈希表?这是因为哈希表是一个可以支持快速查找的数据结构:给定一个元素,我们可以在 O(1)O(1) 的时间查找该元素是否在哈希表中。因此,我们可以考虑将给定的数组设计成哈希表的「替代产品」。 102 103 实际上,对于一个长度为 NN 的数组,其中没有出现的最小正整数只能在 [1, N+1][1,N+1] 中。这是因为如果 [1, N][1,N] 都出现了,那么答案是 N+1N+1,否则答案是 [1, N][1,N] 中没有出现的最小正整数。这样一来,我们将所有在 [1, N][1,N] 范围内的数放入哈希表,也可以得到最终的答案。而给定的数组恰好长度为 NN,这让我们有了一种将数组设计成哈希表的思路: 104 105 我们对数组进行遍历,对于遍历到的数 xx,如果它在 [1, N][1,N] 的范围内,那么就将数组中的第 x-1x−1 个位置(注意:数组下标从 00 开始)打上「标记」。在遍历结束之后,如果所有的位置都被打上了标记,那么答案是 N+1N+1,否则答案是最小的没有打上标记的位置加 11。 106 107 那么如何设计这个「标记」呢?由于数组中的数没有任何限制,因此这并不是一件容易的事情。但我们可以继续利用上面的提到的性质:由于我们只在意 [1, N][1,N] 中的数,因此我们可以先对数组进行遍历,把不在 [1, N][1,N] 范围内的数修改成任意一个大于 NN 的数(例如 N+1N+1)。这样一来,数组中的所有数就都是正数了,因此我们就可以将「标记」表示为「负号」。算法的流程如下: 108 109 我们将数组中所有小于等于 00 的数修改为 N+1N+1; 110 111 我们遍历数组中的每一个数 xx,它可能已经被打了标记,因此原本对应的数为 |x|∣x∣,其中 |\,|∣∣ 为绝对值符号。如果 |x| \in [1, N]∣x∣∈[1,N],那么我们给数组中的第 |x| - 1∣x∣−1 个位置的数添加一个负号。注意如果它已经有负号,不需要重复添加; 112 113 在遍历完成之后,如果数组中的每一个数都是负数,那么答案是 N+1N+1,否则答案是第一个正数的位置加 11。 114 115 作者:LeetCode-Solution 116 链接:https://leetcode-cn.com/problems/first-missing-positive/solution/que-shi-de-di-yi-ge-zheng-shu-by-leetcode-solution/ 117 来源:力扣(LeetCode) 118 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。*/ 119 //若线性表为空,则返回0 120 if (plist==NULL)return 0; 121 for (int i = 0; i < plist->curNum; ++i) { 122 if (plist->element[i] <= 0) 123 { 124 plist->element[i] = plist->curNum + 1; 125 } 126 } 127 for (int i = 0; i < plist->curNum; ++i) { 128 int num = abs(plist->element[i]); 129 if (num <= plist->curNum) 130 { 131 plist->element[num - 1] = -abs(plist->element[num - 1]); 132 } 133 } 134 for (int i = 0; i < plist->curNum; ++i) { 135 if (plist->element[i] > 0) 136 { 137 return i + 1; 138 } 139 140 } 141 return plist->curNum + 1; 142 } 143 144 //第三关:找出给定目标值target在有序线性表中出现的起始位置和结束位置 145 void findPos(PseqList plist,int target, int *pos) 146 { 147 //起始位置放在pos[0], 结束位置放在pos[1] 148 searchRange( plist, target, pos); 149 150 } 151 152 153 154 155 int binarySearch(PseqList plist,int target, int *pos, bool lower) 156 { 157 int begin = 0; 158 int end = plist->curNum - 1; 159 int ans = plist->curNum; 160 while (begin <= end) 161 { 162 int mid = (begin+ end ) / 2; 163 if (plist->element[mid] > target || (lower && plist->element[mid] >= target)) 164 { 165 end = mid - 1; 166 ans = mid; 167 }else 168 { 169 begin = mid + 1; 170 } 171 } 172 return ans; 173 174 } 175 void searchRange(PseqList plist,int target, int *pos) 176 { 177 int leftIdx = binarySearch(plist,target,pos, true); 178 int rightIdx = binarySearch(plist,target,pos, false) - 1; 179 180 if (leftIdx <= rightIdx && rightIdx < plist->curNum && plist->element[leftIdx] == target && plist->element[rightIdx] == target) { 181 pos[0] = leftIdx, pos[1] = rightIdx; 182 return; 183 } 184 pos[0] = -1, pos[1] = -1; 185 186 } 187 188 189 #endif //CONTINUOUSSUBTABLESFIND_SEQLIST_H