通過本文,你將學到如何簡單地優化算法和編程的基本方法-----套用,同時,你將更加理解字符串。
假設有(int []){1,2,3,4,5},要將它變成(int []){5,4,3,2,1},該怎麼辦?這就是我們今天要探究的數組顛倒問題。雖然這個東西似乎沒什麼太大用處,但對於提高編程能力有一定幫助。我們先通過一個圖來分析如何顛倒一個整型數組。
將左邊的數組按照線段的指示依次調換線段端點指向的元素,就可以變成右邊的數組。由於整型數組每一個元素都是普通的(不像字符串那樣用'\0'結尾)。所以對於整型數組的顛倒就十分容易。我們現在來設計算法。
直接由上圖得出,我們需要用兩個變量來表示線段的兩端。對於奇數個元素的數組,我們這樣編寫類C偽代碼:
for(i = 0 , j = SIZE - 1; i != j; i++, j--)
temp = array[i];
array[i] = array[j];
array[j] = temp;
對於偶數個元素的數組,我們這樣編寫類C偽代碼:
for(i = 0, j = SIZE - 1; i < j; i++, j--)
temp = array[i];
array[i] = array[j];
array[j] = temp;
優化之後,我們發現 j = SIZE - i - 1 ,i < SIZE / 2而且當元素個數為偶數個時,i 不會等於 j 。綜合後得出代碼:
#include <stdio.h> #include <stdlib.h> #define SIZE 10 int main(int argc, char * argv[]){ int i, temp, array[SIZE] = {1,2,3,4,5,6,7,8,9,10}; for(i = 0; i < SIZE / 2; i++){ temp = array[i]; array[i] = array[SIZE - i - 1]; array[SIZE - i - 1] = temp; } for(i = 0; i < SIZE; i++) printf("%d ",array[i]); getch(); return 0; }
運行結果:
我們已經比較了解字符串了(我的上一篇隨筆介紹得比較詳細)。由於字符串是由字符加'\0'組成,相當於一個字符數組,所以也能進行顛倒操作。如果你把上面用來顛倒整型數組的代碼直接用在字符串上,肯定會出錯。我想說的是,整型數組它的每一個元素都是普通的,沒有什麼特殊意義,但是字符串有一種元素很特別,那就是內容為'\0'的元素,它標志著字符串的結束,也區別著字符數組和字符串。所以,如果按前面的思路去顛倒,試問字符串的第一個元素就是'\0'了,那後面的元素不就沒有意義了嗎?反而還會使程序不穩定,後續的代碼可能會讀錯緩沖區。我們還是來看一張圖,這樣對後續的算法設計有很大幫助。
大徹大悟了吧?這也就是說,字符串顛倒實際上就是顛倒字符數組中元素內容為\0前的所有元素構成的子數組。我們就可以簡單地設計偽代碼。
計算子數組大小
顛倒子數組
我們可以通過strlen()函數計算出這個字符串的長度,實際上就是計算出子數組的元素個數,然後再套用整型數組的顛倒方法來顛倒子數組。我打算自己設計一個測試這個子數組元素個數的過程。現在,完整的代碼如下:
#include <stdio.h> #include <stdlib.h> #define SIZE 10 int main(int argc, char * argv[]){ char temp, st[SIZE] = "China"; int i,size; for(size = 0; st[size] != '\0'; size++) continue; //如果元素內容不為0就遞增1,得到子數組元素個數 for(i = 0; i < size / 2; i++){ temp = st[i]; st[i] = st[size - i - 1]; st[size - i - 1] = temp; } puts(st); getch(); return 0; }
運行結果:
嘗試使用簡單的排序方法對字符串進行排序。提示:使用char指針構成的數組指向字符串,然後按排序這個數組。