1. 程式人生 > 實用技巧 >順序線性表——實驗及提升訓練

順序線性表——實驗及提升訓練

  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
edu
  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
clion