顺序线性表——实验及提升训练

  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

 

posted @ 2020-12-23 21:19  ethon-wang  阅读(582)  评论(0编辑  收藏  举报