1、給定一組“無序”記錄序列{25, 30, 11, 7, 22, 16, 18, 33, 40, 55},採用冒泡排序、堆排序、直接選擇排序以及直接插入排序方法,將該序列排成非遞減序列,完成以下問題:
1)寫出冒泡排序、堆排序、直接選擇排序和直接插入排序方法的Java實現代碼。
2)採用上述4種方法進行排序時,都要執行的兩種基本操作是什麼?
3)寫出冒泡排序第二趟排序後的結果。
4)畫出採用堆排序方法第一次抽取堆頂元素後得到的最小堆。
5)採用直接選擇法排序時,第5次交換和選擇後,未排序記錄是什麼?
6)採用直接插入法排序把第6個記錄16插入有序表時,爲尋找插入位置,需要比較多少次?
7)試比較上述4種排序算法的性能(時間複雜度)。
2、問題提出:公元前5世紀末,中國古代數學家張丘建在他的《算經》中提出了著名的 “百錢買百雞問題”:雞翁一,值錢五,雞母一,值錢三,雞雛三,值錢一,百錢買百雞,問翁、母、雛各幾何?即一百個銅錢買了一百隻雞,其中公雞一隻5錢、母雞一隻3錢,雛雞一錢3只,問一百隻雞中公雞、母雞、雛雞各多少? 算法的僞代碼如下:
for x = 0 to 100
for y = 0 to 100
for z = 0 to 100
if (x+y+z=100) and (5*x + 3*y + z/3 = 100) then
System.out.println(" "+x+" "+y+" "+z)
end if
實驗要求:對上述算法做出改進以提高算法的效率,要求將算法的時間複雜性由Ο(n3)降爲 Ο(n2),並將改進的算法編程實現。
3、硬件廠商XYZ公司宣稱他們研製的微處理器的運行速度是其競爭對手ABC公司同類產品的1000倍。對於計算複雜性分別爲,,的各類算法,若用ABC公司的計算機能在1小時內解決輸入規模爲的問題,則用XYZ公司的計算機在1小時內能解決多大輸入規模的問題?
4、假設某算法在輸入規模爲n時的計算時間爲。在某臺計算機上,於t秒內實現並完成該算法。現有另一臺計算機,其運行速度爲第一臺的128倍,那麼在這臺新機器上用同一算法在t秒內能解決多大輸入規模的問題?
1)
int num[] = new int[] { 25, 30, 11, 7, 22, 16, 18, 33, 40, 55 };
int len = num.length;
// 冒泡排序
public void bubbleSort() {
for (int i = 1; i < len; i++) {// n-1趟
int temp;
for (int j = 0; j < len - i; j++) {
if (num[j] > num[j + 1]) {
temp = num[j];
num[j] = num[j + 1];
num[j + 1] = temp;
}
}
}
}
// 堆排序
int leng = num.length;
List<Object> list = new ArrayList<Object>();
public void heapSort() {
for(int j = 0; j < leng; j++) {
for (int i = len / 2 - 1 ; i >= 0; i--) {// 創建堆
siftSmall(i, len);
}
list.add(num[0]);
num = remove(num,0);
len--;
}
for (Object n : list) {
System.out.print(n + " ");
}
}
private static int[] remove(int[] arr, int num) {
int[] tmp = new int[arr.length - 1];
int idx = 0;
boolean hasRemove = false;
for (int i = 0; i < arr.length; i++) {
if (!hasRemove && i == num) {
hasRemove = true;
continue;
}
tmp[idx++] = arr[i];
}
return tmp;
}
// 創建最小堆
public void siftSmall(int low, int high) {
int i = low;// 子樹的根結點
int j = 2 * i + 1; // j爲i結點的左孩子
int temp = num[i];
while (j < high) { // 沿着較小值孩子結點向下篩選
if (j < high - 1 && num[j] > num[j + 1]) {
j++;// 記錄比較,j爲左右孩子的較小者
}
if (temp > num[j]) {// 若父結點較大
num[i] = num[j];// 孩子結點中較小者上移
i = j;
j = 2 * i + 1;
} else {
j = high + 1;
}
}
num[i] = temp;
}
// 直接選擇排序
public void selectSort() {
int temp;
for (int i = 0; i < len; i++) {// n-1趟
int min = i;
for (int j = i + 1; j < len; j++) {
if (num[j] < num[min]) {
min = j;
}
}
if (min != i) {
temp = num[i];
num[i] = num[min];
num[min] = temp;
}
}
}
// 直接插入排序
public void insertSort() {// 將比較後較大數放在後一位
for (int i = 1; i < len; i++) {
// 準備插入的數
int temp = num[i];
int j = i - 1;
for (; j >= 0 && temp < num[j]; j--) {
num[j + 1] = num[j];
}
num[j + 1] = temp;// 將數組後一位數賦值,插入排序
}
}
2)比較數值大小、元素交換
3) 11 25 30 7 22 16 18 33 40 55
4)
5)16、18、33、40、55
6) 3次
7)冒泡排序O(n^2)、堆排序O(nlog2n)、直接選擇排序O(n^2)、直接插入排序O(n^2)
2.
public void test() {
for (int x = 0; x <= 20; x++) {
for (int y = 0; y <= 33; y++) {
if (5 * x + 3 * y + (100 - x - y) / 3 == 100 && (100 - x - y) % 3 == 0) {
System.out.println(x + " " + y + " " + (100 - x - y) + " ");
}
}
}
}
實現代碼運行效果如下圖
3.
時間複雜度爲n時,輸入規模1000n
時間複雜度爲時,輸入規模 ²√1000 ≈31.623
時間複雜度爲時,輸入規模10n
4.
某臺機器t秒內完成算法的計算時間
新機器t秒內完成算法的計算時間=128*3*2^n=2^7*3*2^n=3*2^(n+7)
T=T(n)=3*2^n
n=log2(T/3)
設新機器輸入規模爲n1,則:
n1=log2(3*2^(n+7)/3)=n+7