使用結構體實現連續存儲數組增刪改查等各種操作


這次主要是利用結構體實現一個長度可變數組的增刪改查等各個操作。因為這里郝斌老師還沒講typedefy的使用,所以我也是跟着他使用了最原始的方法,一個個敲,發現這樣敲下來,也給自己鞏固了很多淡忘的知識。

自己基本是在視頻里說了方法后自己先思考然后實現的,結果犯了兩個低級錯誤:1、錯誤的使用函數值傳遞來改變值 2、貪圖簡便沒用大括號導致else與if結合錯誤,如果沒有大括號干擾,else總是與自己上面最近的一個if結合。

這里是使用結構體Arr來模擬這個數組的,結構體Arr中有三個成員變量,分別是數組的首元素地址、當期數組長度、當前數組中有效元素個數

1 struct Arr
2 {
3     int *pBase;//存儲的是數組第一個元素的地址,可以動態分配一塊內存空間給它,讓它指向第一個元素。
4     int len;//數組所能容納的最大元素個數
5     int cnt;//當前數組有效元素的個數
6 };

 

這里主要是實現了增加、插入、刪除、排序、倒置的功能。

 

增加:如果滿了則提示錯誤,返回false。成功則返回true

 1 bool append_arr(struct Arr* pArr, int val)
 2 {
 3     if (true == is_full(pArr))
 4     {
 5         printf("該數組已經滿了。追加失敗!\n");
 6         return false;
 7     }
 8     else
 9     {
10         //pArr->pBase[pArr->cnt] = val;
11         *(pArr->pBase + pArr->cnt) = val;
12         pArr->cnt++;
13         return true;
14     }
15 }

 

插入:將一個值val插入到pArr指向的結構體變量的數組第pos個值的前面.如果該位置前面沒有值,或者該數組滿了,均提示錯誤,返回false。如果插入成功返回true

 1 bool insert_arr(struct Arr* pArr,int pos,int val)
 2 {
 3     int i,temp;
 4     if (true == is_full(pArr) || pos < 1 || pos > pArr->cnt+1)
 5     {
 6         printf("插入失敗!\n");
 7         return false;
 8     }
 9     else
10     {
11         for (i = pArr->cnt-1;i >= pos-1;i--)
12             pArr->pBase[i + 1] = pArr->pBase[i];
13         pArr->pBase[pos-1] = val;
14         pArr->cnt++;
15         return true;
16     }
17 }

 

刪除:刪除pArr指向的結構體變量的數組第pos個的值,如果成功,將這個值放到pVal指向的變量里,返回true,如果數組為空或者這個位置沒有值,返回false

 1 bool delete_arr(struct Arr* pArr,int pos,int * pVal)
 2 {
 3     int i;
 4     if (true == is_empty(pArr) || pos<1 || pos>pArr->cnt)
 5     {
 6         printf("刪除失敗!\n");
 7         return false;
 8     }
 9     else
10     {
11         *pVal = pArr->pBase[pos - 1];
12         for (i = pos;i <= pArr->cnt - 1;i++)
13             pArr->pBase[i - 1] = pArr->pBase[i];
14         pArr->cnt--;
15         return true;
16     }
17 }

 

排序:這里使用的是冒泡排序,當flag為0則表示降序,其他值則為升序

 1 void sort_arr(struct Arr* pArr,int flag)
 2 {
 3     int i, j;
 4     if (true == is_empty(pArr))
 5         return;
 6     for(i = 0;i < pArr->cnt-1;i++)
 7         for (j = i + 1;j < pArr->cnt;j++)
 8         {
 9             if (0 == flag)
10             {
11                 if (pArr->pBase[i] < pArr->pBase[j])
12                     exchange(&(pArr->pBase[i]), &(pArr->pBase[j]));
13             }
14             else
15                 if (pArr->pBase[i] > pArr->pBase[j])
16                     exchange(&(pArr->pBase[i]), &(pArr->pBase[j]));
17         }
18 }

 

倒置:將整個數組倒置。比如 3 12 45 6 —–>> 6 45 12 3 這里我使用了兩種方法倒置:

第一種:直接不斷調換前后的值,直至全部被調換。(時間復雜度相對較高)

 1 void inversion_arr(struct Arr* pArr)
 2 {
 3     int length,leftIndex,rightIndex;
 4     if (true == is_empty(pArr))
 5     {
 6         printf("倒置失敗!\n");
 7         return;
 8     }
 9     length = pArr->len;
10     //第一種
11     for (leftIndex = 0, rightIndex = pArr->cnt - 1;leftIndex < rightIndex;leftIndex++, rightIndex--)
12         exchange(&(pArr->pBase[leftIndex]),&(pArr->pBase[rightIndex]));
13 }

 

第二種:重新申請一塊內存,將值一一復制過來,然后改變結構體變量中指針的指向。最后將原地址的內存釋放(空間復雜度相對較高)

 1 void inversion_arr(struct Arr* pArr)
 2 {
 3     int length,leftIndex,rightIndex;
 4     if (true == is_empty(pArr))
 5     {
 6         printf("倒置失敗!\n");
 7         return;
 8     }
 9     length = pArr->len;
10     //第二種
11     int * pTest = (int *)malloc(sizeof(int)*length);
12     int * freeP;
13     int i;
14     for (i = 0;i < pArr->cnt;i++)
15         pTest[pArr->cnt-i-1] = pArr->pBase[i];
16     freeP = pArr->pBase;//先將原地址拿到
17     pArr->pBase = pTest;//再更換指向的地址
18     free(freeP);//將之前拿到的原地址內存釋放掉
19 }

 

下面是完整的程序:

  1 #include<stdio.h>
  2 #include<windows.h>
  3 //定義了一個復合數據類型,該數據名字叫 struct Arr,它包含了三個基礎數據類型 
  4 struct Arr
  5 {
  6     int *pBase;//存儲的是數組第一個元素的地址,可以動態分配一塊內存空間給它,讓它指向第一個元素。
  7     int len;//數組所能容納的最大元素個數
  8     int cnt;//當前數組有效元素的個數
  9 };
 10 
 11 void init_arr(struct Arr* pArr,int length);//初始化
 12 bool append_arr(struct Arr* pArr,int val);//追加
 13 bool insert_arr(struct Arr* pArr,int pos,int val);//將val插入到pArr指向的結構體變量的數組第pos個的值的前面.
 14 bool delete_arr(struct Arr* pArr,int pos,int *pVal);//刪除函數,刪除pArr指向的結構體變量的數組第pos個的值,如果成功,將這個值放到pVal指向的變量里
 15 bool is_empty(struct Arr* pArr);//判斷數組是否為空
 16 bool is_full(struct Arr* pArr);//判斷數組是否已經滿了
 17 void sort_arr(struct Arr* pArr,int flag);//冒泡排序,flag為0則表示降序,其他值則為升序
 18 void show_arr(struct Arr* pArr);//顯示數組的值
 19 void inversion_arr(struct Arr* pArr);//倒置數組
 20 
 21 void exchange(int* a, int* b);//更換兩個整型變量的值
 22 
 23 int main(void)
 24 {
 25     int val;
 26     struct Arr arr;//整出了一個struct Arr類型的對象,不過未賦值,里面目前都是垃圾數值
 27     init_arr(&arr,6);
 28 
 29     //追加值,然后插入值,最后顯示
 30     append_arr(&arr, 2);
 31     append_arr(&arr, 13);
 32     append_arr(&arr, 7);
 33     insert_arr(&arr, 4, 45);
 34     show_arr(&arr);
 35 
 36     //刪除一個值,然后顯示
 37     if (delete_arr(&arr, 4, &val))
 38         printf("你刪除的元素為%d\n",val);
 39     show_arr(&arr);
 40 
 41     //倒置整個數組,然后顯示
 42     inversion_arr(&arr);
 43     show_arr(&arr);
 44 
 45     //排序后顯示
 46     sort_arr(&arr,1);
 47     show_arr(&arr);
 48 
 49 
 50     system("pause");
 51     return 0;
 52 }
 53 
 54 //初始化
 55 void init_arr(struct Arr* pArr,int length)
 56 {
 57     //通過結構體變量指針訪問結構體變量中的成員有兩種方式:1、通過(*probe).valuable   2、通過probe->valuable
 58 
 59     pArr->pBase = (int *)malloc(sizeof(int)*length);
 60     if (NULL == pArr->pBase)//如果分配內存失敗
 61     {
 62         printf("動態內存分配失敗!\n");
 63         exit(-1);//終止整個程序
 64     }
 65     else
 66     {
 67         (*pArr).len = length;
 68         pArr->cnt = 0;
 69     }
 70     return;
 71 }
 72 
 73 void show_arr(struct Arr* pArr)
 74 {
 75     int i;
 76     //如果為空,直接提示為空。否則輸出有效內容
 77     if (true == is_empty(pArr))
 78     {
 79         printf("該數組為空\n");
 80     }
 81     else
 82     {
 83         for (i = 0;i < pArr->cnt;i++)
 84         {
 85             //下面兩種方法皆可以
 86             printf("%d ",pArr->pBase[i]);  //數組的地址存在pArr->pBase中,這個東西可以當成數組名來使用
 87             //printf("%d\n",*(pArr->pBase+i));  //將地址加i,即指向的地址往后移多少,然后通過*取出值
 88         }
 89         printf("\n");
 90     }
 91 }
 92 
 93 bool  is_empty(struct Arr* pArr)
 94 {
 95     //判斷結構體變量中的有效個數是否為0,如果為零則表示這個數組為空,返回true
 96     if (0 == pArr->cnt)
 97         return true;
 98     else
 99         return false;
100 }
101 
102 bool is_full(struct Arr* pArr)
103 {
104     if (pArr->len == pArr->cnt)//如果長度和有效個數相等,則滿了
105         return true;
106     else
107         return false;
108 }
109 
110 bool append_arr(struct Arr* pArr, int val)
111 {
112     //判斷是否滿了,如果滿了,則追加失敗,返回false
113     //否則將值添加到數組里,將有效個數加1
114     if (true == is_full(pArr))
115     {
116         printf("該數組已經滿了。追加失敗!\n");
117         return false;
118     }
119     else
120     {
121         //兩種賦值方法都可以
122         //pArr->pBase[pArr->cnt] = val;
123         *(pArr->pBase + pArr->cnt) = val;
124         pArr->cnt++;
125         return true;
126     }
127 
128 }
129 
130 bool insert_arr(struct Arr* pArr,int pos,int val)
131 {
132     int i,temp;
133     //先判斷是否能夠插入值。如果不能插入值,則返回false:判斷是否滿了,以及pos是否合理
134     //如果能夠插入值,則先將這個下標的值及后面的值都往后移一位。
135     //移動方法:先通過數組有效元素個數,將最后的一個值往后移一位,然后再將前面一個的值往后移一位。直到pos
136     //然后將pos位置的值變成val,將有效個數加1,返回true;
137     if (true == is_full(pArr) || pos < 1 || pos > pArr->cnt+1)
138     {
139         printf("插入失敗!\n");
140         return false;
141     }
142     else
143     {
144         for (i = pArr->cnt-1;i >= pos-1;i--)
145         {
146             pArr->pBase[i + 1] = pArr->pBase[i];
147         }
148         pArr->pBase[pos-1] = val;
149         pArr->cnt++;
150         return true;
151     }
152 }
153 
154 
155 bool delete_arr(struct Arr* pArr,int pos,int * pVal)
156 {
157     //如果數組為空則失敗
158     //如果pos的值不合理,也返回失敗。
159     //否則,將第pos位的值給pVal指向的變量
160     //並將pos后面的值依次賦給前面的一位,直到有效個數的值也賦給了前面一位,讓有效位數減1,返回成功
161     int i;
162     if (true == is_empty(pArr) || pos<1 || pos>pArr->cnt)
163     {
164         printf("刪除失敗!\n");
165         return false;
166     }
167     else
168     {
169         *pVal = pArr->pBase[pos - 1];
170         for (i = pos;i <= pArr->cnt - 1;i++)
171             pArr->pBase[i - 1] = pArr->pBase[i];
172         pArr->cnt--;
173         return true;
174     }
175 }
176 void inversion_arr(struct Arr* pArr)
177 {
178     //倒置整個數組
179     //先判斷數組是否為空,如果為空,直接返回
180     //如果不為空,兩種方案。
181     //第一種:引入一個中間變量、一個左下標、一個右下標。左右下標初始分別為0和有效個數減1.通過中間變量交換值,左右下標往中間靠。時間復雜度相對高一些。
182     //第二種,重新開辟一個同樣長度的數組,從后往前依次給新數組賦值,然后直接改變結構體變量中數組的地址,即pBase的指向.此方法空間復雜度相對高一些。
183     int length,leftIndex,rightIndex;
184     if (true == is_empty(pArr))
185     {
186         printf("倒置失敗!\n");
187         return;
188     }
189     length = pArr->len;
190     //第一種
191     /*for (leftIndex = 0, rightIndex = pArr->cnt - 1;leftIndex < rightIndex;leftIndex++, rightIndex--)
192         exchange(&(pArr->pBase[leftIndex]),&(pArr->pBase[rightIndex]));*/
193 
194     //第二種
195     int * pTest = (int *)malloc(sizeof(int)*length);
196     int * freeP;
197     int i;
198     for (i = 0;i < pArr->cnt;i++)
199         pTest[pArr->cnt-i-1] = pArr->pBase[i];
200     freeP = pArr->pBase;//先將原地址拿到
201     pArr->pBase = pTest;//再更換指向的地址
202     free(freeP);//將之前拿到的原地址內存釋放掉
203 }
204 
205 void sort_arr(struct Arr* pArr,int flag)
206 {
207     //如果為空,直接返回。
208     //否則,根據flag的值,使用冒泡排序。升序或者是降序
209     int i, j;
210     if (true == is_empty(pArr))
211     {
212         return;
213     }
214     for(i = 0;i < pArr->cnt-1;i++)
215         for (j = i + 1;j < pArr->cnt;j++)
216         {
217             //2018年3月27日 20:08:07
218             //這里犯了個很低級的錯誤。。。如果沒有大括號干擾,else總是與自己上面最近的一個if結合起來。
219             //所以這里相當於是 如果flag不為0,則不做處理,如果為0,且前面的小於后面的,則交換位置。
220 
221             /*if (0 == flag)
222                 if (pArr->pBase[i] < pArr->pBase[j])
223                     exchange(&(pArr->pBase[i]),&(pArr->pBase[j]));
224             else
225                 if (pArr->pBase[i] > pArr->pBase[j])
226                     exchange(&(pArr->pBase[i]), &(pArr->pBase[j]));*/
227 
228             if (0 == flag)
229             {
230                 if (pArr->pBase[i] < pArr->pBase[j])
231                     exchange(&(pArr->pBase[i]), &(pArr->pBase[j]));
232             }
233             else
234                 if (pArr->pBase[i] > pArr->pBase[j])
235                     exchange(&(pArr->pBase[i]), &(pArr->pBase[j]));
236         }
237 
238 }
239 
240 //更換兩個整型變量的值!一定記得需要通過指針改變值,傳遞值是無法修改原來的變量值的
241 void exchange(int* a, int* b)
242 {
243     int temp;
244     temp = *a;
245     *a = *b;
246     *b = temp;
247 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM