順序線性表——實驗及提升訓練
阿新 • • 發佈:2020-12-23
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;//用於存放順序線性表資料元素的連續空間的起始地址edu11 }; 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 = (structseqList *)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 returnNULL; 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_Hclion