算法入門第一篇

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章