1. 程式人生 > >第四章演算法實踐

第四章演算法實踐

1.實踐題目

 

7-1 最優合併問題 (100 分)

題目來源:王曉東《演算法設計與分析》

給定k 個排好序的序列, 用 2 路合併演算法將這k 個序列合併成一個序列。 假設所採用的 2 路合併演算法合併 2 個長度分別為m和n的序列需要m+n-1 次比較。試設 計一個演算法確定合併這個序列的最優合併順序,使所需的總比較次數最少。 為了進行比較,還需要確定合併這個序列的最差合併順序,使所需的總比較次數最多。

輸入樣例:

4

5 12 11 2

輸出樣例:

78 52

2.問題描述

將幾個序列合併成一個序列,序列的比較次數的計算方式是序列長度分別為m和n的序列為m+n-1 次。計算最多比較次數時,從待選序列中選取最長的兩個序列合併成新的序列,繼續比較合併直至合併成最終序列,同理於最少比較次數的方法,只是合併最短序列。

程式碼如下:

#include<iostream>

using namespace std;

 

int getmax(int a[],int n){

    int number=n,result=0,s[n];

    int i,j,temp;

    for(i=0;i<n;i++){

        s[i]=a[i];

    }

    while(number>1){

        for(i=0;i<number;i++){

            for(j=i+1;j<number;j++){

                if(s[i]<s[j]){

                    temp=s[i];s[i]=s[j];s[j]=temp;

                }

            }

        }

        s[0]=s[0]+s[1];

        result+=s[0]-1;

        number--;

        for(i=1;i<number;i++)

            s[i]=s[i+1];

    }

    return result;

}

 

int getmin(int a[],int n){

    int number = n,result=0,s[n];

    int i,j,temp;

 

    for(i=0; i<n; i++){

        s[i]=a[i];

    }

    while(number>1){

        for(i=0;i<number;i++){

            for(j=i+1;j<number;j++){

                if(s[i]>s[j]){

                    temp=s[i];s[i]=s[j];s[j]=temp;

                }

            }

        }

        s[0]=s[0]+s[1];

        result+=s[0]-1;

        number--;

        for(i=1;i<number;i++)

            s[i]=s[i+1];

    }

    return result;

}

 

int main()

{

    int n;

    cin >> n;

    int *a = new int[n];

    for(int i=0;i<n;i++)

    {

             cin >> a[i];

    }

         cout << getmax(a,n) << " " <<getmin(a,n);

    return 0;

}

3.

時間複雜度:O(nlongn)

空間複雜度:O(n) 

4.心得:感覺這道,題跟之前幾道實踐題類似,在最開始寫演算法時,編寫了冒泡演算法,雖然可以計算正確,演算法的操作時間和程式碼數都不少,較為冗餘。自己編寫的演算法缺點很明顯,在編寫演算法程式碼這方面較為薄弱,下次還要繼續改進