序:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
下述的作業題源自<<Java數據結構和算法(第二版)>>每章結束後留給的問題,它們涵蓋了每章的所有重點。目地在於自測,以確保自己已經基本理解該章的內容。
第3章 簡單排序
問題
1、 計算機排序算法與人類排序相比較,它的侷限性是:D
A、 人類擅長髮明新算法。
B、 計算機只能處理數量固定的數據。
C、 人類知道什麼需要排序,而計算機不知道。
D、 計算機一次只能比較兩件東西。
解:計算機程序不能像人這樣通覽所有的數據。它只能根據計算機的“比較”操作原理,在同一時間內對兩個數據進行比較。
2、 簡單排序算法中的兩個基本操作是比較兩個數據項和交換兩個數據項(或複製其中一項)。
解:這一章中的三個算法(冒泡排序、選擇排序和插入排序)都包括如下的兩個驟,這兩步循環執行,直到全部數據有序止:
1、 比較兩個數據項。
2、 交換兩個數據項,或複製其中一項。
3、 判斷題:冒泡排序算法總是在所有數據項兩兩比較完成後停止。假
解:冒泡排序遵循的規則:
1、 比較兩個數據項。
2、 如果左邊的數據項大,則兩數據項交換位置。
3、 向右稱動一個位置,比較下面兩個隊員。
沿着這個隊列照剛纔那樣比較下去,一直比較到隊列的最右端。
4、 冒泡排序算法在哪兩者之間交替進行:A
A、比較和交換。
B、 移動各複製。
C、 移動各比較。
D、複製和比較。
解:請看判斷題3的解。
5、 判斷題:有N個數據項,冒泡排序算法精確操作了N*N次比較。假
解:算法作了大約N2/2(備註1)次比較。
6、 選擇排序中B
A、最大的關鍵字聚集到左邊(較小的下標)。
B、 最小的關鍵字被重複的發現。
C、 爲了將每個數據項插入到正確排序的位置,很多數據項將被移動。
D、有序的數據項聚集在右邊。
解:進行選擇排序就是把所有的數據項掃描一趟,從中挑出最小的關鍵字。這個最小的關鍵字和和最左端的數據項交換位置,即站到0號位置。現在最左端的數據項是有序的了。不需要交換位置了。再次掃描所有數據項時,就從1號位置開始,還是尋找最小關鍵字,然後和1號位置的數據項交換。這個過程一直持續到所有的數據項都排定。
7、 判斷題:在某個特定的排序情況中,如果交換與比較相比費時得多,那麼選擇排序將比冒泡排序快大約一倍。假
解:選擇排序改進了冒泡排序,將必要的交換次數從O(N2)減少到O(N)不幸的是比較次數仍保持爲O(N2)。
8、 複製是交換的三倍。
9、 選擇排序中不變性是什麼?
答:下標小於或等於out的項進行排序。
10、插入排序中,文中描述的“被標記的隊員”對應於insertSort.java中的哪個變量?C
A、in
B、 out
C、 temp
D、a[out]
11、在插入排序中,“局部有序”是指:D
A、一些數據項已經排序了,但它們可能需要被移動。
B、 大部分數據項已在它們最終排序的位置了,但仍有一些需要排序。
C、 只有一些數據項有序。
D、組內的數據項已排序好序,而組外面的數據項需要插入到組中來。
12、向左或向右移動一組數據項需要重複地複製。
13、在插入排序中,一個數據項被插入到局部有序的組合後,它將:B
A、永遠不會再移動。
B、永遠不會向左邊移動。
C、經常被移出這個組。
D、發現這組的數據項不斷減少。
14、插入排序中的不變性是下標小於outer的項部分有序。
15、穩定性是指:B
A、在排序中排除有次關鍵字的項。
B、 在對州進行排序時,每個州的城市還要求按人口遞增有序。
C、 讓相同的名配相同的姓。
D、數據項按照關鍵字有序,不考慮次關鍵字。
編程作業
3.1 bubbleSort.java程序(清單3.1)和BubbleSort專題applet中,in索引變量都是從左到右移動的,直到找到最大數據項並把它移動到右邊的out變量外。修改bubbleSort()方法,使它成爲雙向移動的。這樣,in索引先像以前一樣,將最大的數據項從左移到右,當它到達out變量位置時,它掉頭並把最小的數據項從右移到左。需要兩個外部索引變量,一個在右邊(以前的out變量),另一個在左邊。
3.2在isertSort.java程序(清單3.3)中給ArrayIns類加一個median()方法.這個方法將返回數組的中間值.(回憶一下,數組中一半數據項比中間值大,一半數據項比中間值小。)
3.3在insertSort.java程序(清單3.3)中增加一個名爲noDups()的方法,這個方法從已經有序的數組中刪掉重複的數據項而不破壞有序性。(可以用insertionSort()方法對數據排序,或者也可以簡單地用main()方法將數據有序地插入到表中。)一種解決方法是每發現一個重複的數據,就從這個位置開始到數組結尾都向前移動一個位置,但這樣就導致消耗很長的O(N2)的時間級,起碼在有很多重複數據項的情況下是這樣的。在設計的算法中,不論有多少重複數據,要確保數據項最多隻能移動一次。這樣算法只消耗O(N)數量級的時間。
3.4還有一種簡單排序算法是奇偶排序。它的思路是在數組中重複兩趟掃描。第一趟掃描選擇所有的數據項對,a[j]和a[j+1],j是奇數(j=1,3,5,……)。如果它們的關鍵字的值次序顛倒,就交換它們。第二趟掃描對所有的偶數數據項進行同樣的操作(j=2,4,6,……)。重複進行這樣兩趟的排序直到數組全部有序。用oddEvenSort()方法替換bubbleSort.java程序(清單3.1)中的bubbleSort()方法。確保它可以在不同數據量的排序中運行,還需要算出兩趟掃描的次數。
奇偶排序實際上在多處理器環境中很有用,處理器可以分別同時處理每一個奇數對,然後又同時處理偶數對。因爲奇數對是彼此獨立的,每一對都可以用不同的處理器比較和交換。這樣可以非常快速地排序。
3.5修改insertSort.java程序(清單3.3)中的insertionSort()方法,使它可以計算排序過程中複製和比較的次數並顯示出總數。爲計算比較的次數,要把內層while循環的兩個條件分開。用這個程序測量各種數量的逆序數據排序的複製和比較次數。結果滿足O(N2)嗎?與已經基本有序的數據(僅有很少的數據無序)的情況一樣嗎?從對基本有序數據排序的表現中可得出關於這個算法效率的什麼結論?
問題1:用這個程序測量各種數量的逆序數據排序的複製和比較次數。結果滿足O(N2)嗎?
答:假設有10個數據項以逆序排列(9~0)。這個算法需要多少次比較和複製呢?在第一趟排序中,它最多比較一次,第二趟最多比較兩次,依此類推。最後一趟最多,比較N-1次。因此有
1+2+3+…+N-1=N*(N-1)/2(備註1), 10*(10-1)/2 = 45。
複製的次數大致等於比較的次數。在本例中a[in-1]>=temp每次比較都會成立,所以複製操作也將執行。比較和複製操作次數都和N2成正比。並且認爲運行需要O(N2)時間級別。
問題2:與已經基本有序的數據(僅有很少的數據無序)的情況一樣嗎?
答:給定一個數組,其中數據項按如下所示排列:
0 11 22 44 55 33 66 88 77 99
上述數例排序後比較用了12次、複製3次。對於已經有序或基本有序的數據來說,插入排序要好得多。當數據有序的時候,while循環的條件總是假,所以它變成了外層循環中的一個簡單語句,執行N-1次。在這種情況下,算法運行只需要O(N)的時間。如果數據基本有序,插入排序幾乎只需要O(N)的時間,這對把一個基本有序的文件時行排序是一個簡單而有效的方法。
問題3:從對基本有序數據排序的表現中可得出關於這個算法效率的什麼結論?
答:對於逆序排列的數據,每次比較和移動都會執行,所以插入排序不比冒泡排序快。
3.6有一個有趣的方法用來刪除數組中相同的數據項。插入排序算法中用一個循環嵌套算法,將數組中的每一個數據項與其他數據項一一比較。如果要刪除相同的數據項,可以這樣做(參見第2章第2.6小節)。修改insertSort.java中的insertionSort()方法,使它可以在排序過程中刪除相同的數據項。方法如下:當找到一個重複數據項的時候,通常用一個小於任何值的關鍵值來改寫這個相同數據項(如果所有值都是正數,則可取-1)。於是,一般的插入排序算法就會像處理其他數據項一樣,來處理這個修改了關鍵值的數據項,把它移到下標爲0的位置。從現在開始,算法可以忽略這個數據項。下一個相同的數據項將被移到下標爲1的位置,依此類推。排序完成後,所有相同的數據項(現在關鍵值爲-1)都在數組的開頭部分。可以改變數組的容量並把需要的數據前移動數組下標爲0的位置。
答:這個題目我就不做了,沒有什麼新意。其實就是把noDups()中的代碼和insertionSort()代碼混合後就能達到上述作業要求。
備註1:在數組數據項的線性查找中,我們已經發現尋找特定數據項所需的比較次數平均爲數據項總數的一半。——摘自《Java數據結構和算法(第二版)》第2章數組:大O表示法小節。