最近學計算機軟件基礎,學到了線性表。下面就將線性表中最簡單的順序表的一個簡單示例貼出,方便大家探討。(以及後面對函數傳參的一個小分析,其實這才是重點)
1 ////需求分析 2 //1、線性表遞增有序,刪除重復元素 3 //2、線性表逆置 4 //3、尋求最大值 5 6 #include<stdio.h> 7 8 typedef int ElementType; 9 typedef struct _struct 10 { 11 ElementType SequenceList[100]; 12 ElementType num; 13 }SequenceList; 14 15 void InitSeq(SequenceList **L);//初始化線性表,主要是返回一個SequenceList實例,采用malloc動態開辟內存方式。 16 int Add(SequenceList *L, ElementType value);//想列表中添加項目 17 void Insert(SequenceList *L ,ElementType pos, ElementType value);//插入一個元素 18 void Delete(SequenceList *L, ElementType value);//刪除一個元素 19 ElementType Search(SequenceList *L, ElementType value);//搜索一個元素 20 void RemoveRepetiton(SequenceList *L);//移除所有重復的元素 21 void Transpose(SequenceList *L);//將所有元素位置倒置 22 ElementType MaxValue(SequenceList *L);//求出元素中最大值 23 void Travel(SequenceList *L);//遍歷整個列表(把每個元素都輸出一遍) 24 25 int main() 26 { 27 SequenceList *L; 28 InitSeq(&L); 29 while (1) 30 { 31 int n = 0; 32 int pos; 33 ElementType value; 34 printf("請選擇操作:(1.Add 2.insert 3.delete 4.search 5.transpose 6.maxium 7.travel 8.removeReptitons)\n"); 35 scanf("%d", &n); 36 switch (n) 37 { 38 //add 39 case 1: 40 41 printf("添加新項:"); 42 scanf("%d", &value); 43 Add(L, value); 44 break; 45 //insert 46 case 2: 47 48 printf("選擇位置插入一項:(位置 值)\n"); 49 scanf("%d %d", &pos,&value); 50 Insert(L,pos, value); 51 break; 52 //delete: 53 case 3: 54 printf("輸入刪除內容:"); 55 scanf("%d", &value); 56 Delete(L, value); 57 break; 58 //Search 59 case 4: 60 printf("搜索內容:"); 61 scanf("%d", &value); 62 pos = Search(L, value); 63 if (pos) 64 printf("存在於第%d項。\n", pos); 65 else 66 printf("無法找到!\n"); 67 break; 68 //transpose: 69 case 5: 70 Transpose(L); 71 Travel(L); 72 break; 73 //max 74 case 6: 75 printf("最大值是%d。\n", MaxValue(L)); 76 break; 77 case 7: 78 Travel(L); 79 break; 80 case 8: 81 RemoveRepetiton(L); 82 break; 83 default: 84 break; 85 } 86 } 87 free(L); 88 return 0; 89 } 90 void InitSeq(SequenceList **L) 91 { 92 *L = (SequenceList *)malloc(sizeof(SequenceList)); 93 (*L)->num = -1; 94 } 95 96 int Add(SequenceList *L, ElementType value) 97 { 98 L->num++; 99 if (L->num >= 100) 100 { 101 L->num--; 102 printf("空間已滿!"); 103 return 0; 104 } 105 L->SequenceList[L->num] = value; 106 return 1; 107 } 108 109 void Insert(SequenceList *L, ElementType pos, ElementType value) 110 { 111 if (L->num<0||L->num >= 99) 112 { 113 printf("空間已滿或不足!"); 114 return 0; 115 } 116 if (pos-1 < 0 || pos-1 > L->num) 117 { 118 printf("插入位置錯誤!"); 119 return; 120 } 121 int i; 122 for (i = L->num; i >= pos-1; i--) 123 { 124 L->SequenceList[i+1] = L->SequenceList[i]; 125 } 126 L->SequenceList[pos - 1] = value; 127 L->num++; 128 } 129 130 void Delete(SequenceList *L, ElementType value) 131 { 132 if (L->num < 0) 133 { 134 printf("表為空!"); 135 return; 136 } 137 int i; 138 for (i = 0; i <= L->num; i++) 139 { 140 if (value == L->SequenceList[i]) 141 { 142 int j; 143 for (j = i; j < L->num; j++) 144 { 145 L->SequenceList[j] = L->SequenceList[j + 1]; 146 } 147 L->num--; 148 } 149 } 150 } 151 152 ElementType Search(SequenceList *L, ElementType value) 153 { 154 if (L->num<0) 155 { 156 printf("表空!"); 157 return -1; 158 159 } 160 else 161 { 162 int i; 163 for (i = 0; i <= L->num; i++) 164 { 165 if (value == L->SequenceList[i]) 166 return i + 1; 167 } 168 } 169 170 return 0; 171 } 172 173 void RemoveRepetiton(SequenceList *L) 174 { 175 int count=0; 176 int i; 177 for (i = 0; i <= L->num; i++) 178 { 179 if (Search(L, L->SequenceList[i])) 180 { 181 Delete(L, L->SequenceList[i]); 182 count++; 183 } 184 } 185 printf("共刪除了%d項。", count); 186 } 187 188 void Transpose(SequenceList *L) 189 { 190 ElementType *temp = (ElementType *)malloc(sizeof(ElementType)*(L->num + 1)); 191 int i ,j; 192 for (i = L->num, j = 0; i >= 0; i--,j++) 193 { 194 temp[j] = L->SequenceList[i]; 195 } 196 for (i = 0; i <= L->num; i++) 197 { 198 L->SequenceList[i] = temp[i]; 199 } 200 free(temp); 201 } 202 ElementType MaxValue(SequenceList *L) 203 { 204 int i = 0; 205 ElementType max = L->SequenceList[0]; 206 for (i = 1; i <= L->num; i++) 207 { 208 if (max < L->SequenceList[i]) 209 { 210 max = L->SequenceList[i]; 211 } 212 } 213 return max; 214 } 215 216 void Travel(SequenceList *L) 217 { 218 if (L->num < 0) 219 printf("表空!"); 220 else 221 { 222 int i; 223 for (i = 0; i <= L->num; i++) 224 { 225 printf("%d ", L->SequenceList[i]); 226 if (i>0&&(i % 10 == 0)) 227 printf("\n"); 228 } 229 printf("\n"); 230 } 231 } 點擊查看代碼代碼純手打,不是網上copy過來的。。
代碼中沒什麼算法,搜索、刪除等都用的最簡單的方式。
代碼中唯一值得注意的就是初始化列表的函數InitList(SequenceList **L),傳的是二級指針做參數,為什麼這麼做呢?
下面解釋一下:
我們的目的是在函數InitList中malloc一塊內存空間,用於存放我們的數據。
現在先看我們常寫的一個錯誤寫法
//請看如下錯誤代碼,這是為說明問題的錯誤代碼 void InitList(SequenceList *L) { L=(SequenceList *)malloc(sizeof(SequenceList));//語法重點。。 L->num=-1;//這個是程序功能的一部分 }
許多的初學者認為我們傳到函數InitList中的是一個指針變量,在InitList中可以對該指針變量進行賦值操作,以便達到修改主函數中變量的目的,於是乎便將malloc開辟的空間首地址賦給L,然後在主函數中對L操作的時候發現要麼是亂碼,要麼是不可訪問之類的錯誤,百思不得其解,為什麼呢?
原因很簡單,就是對函數參數的傳遞方式不明確造成的。在此處應該記著,函數傳參始終是將你所傳變量復制後的副本傳進去,並不是該變量本身。
代入這個實際問題,我們在主函數中做如下操作
//為錯誤情況的示例代碼,切記
void main() { SequenceList *L; InitList(L); ...... }
我們為函數InitList傳遞的是一個SequenceList類型的指針變量L,假設L此時指向內存0x10000,則在實際傳參數的時候,系統會對L變量作一個復制操作,假設這兒使復制後的變量為P,則P指向的地址也為L指向的地址0x10000。
現在重點來了,我們為InitList傳遞參數L,但系統實際傳遞的參數是P(P是L的副本,他們指向同一塊內存區域,但他們各自的地址不同),在函數InitList內部,則實際是對P變量進行操作,把malloc的地址(假設為0x30000)賦值給P,
所以P指向的地址是0x30000,但是主函數中的L仍然指向0x10000,所以就造成了我們遇見的錯誤,因為我們根本沒有把L指向的地址改為malloc的地址;
那麼接下來看正確的操作。
//以下代碼為正確代碼 void main() { SequenceList *L; InitList(&L); } void InitSeq(SequenceList **L) { *L = (SequenceList *)malloc(sizeof(SequenceList)); (*L)->num = -1; }
我們傳參數的時候傳的是變量L的地址,那麼系統實際傳的是變量P,P與L有如下關系:P=&L(P指向變量L的地址).在函數InitList中
*L = (SequenceList *)malloc(sizeof(SequenceList));
L是P,*L即是主函數中的L,現在用malloc的地址給*L,就實現了為主函數中L賦值的操作。
明白了嗎?這是我個人的理解。可能系統在某些細節上和我說的不一樣,但我這個思路應該是沒錯的。