排序實訓

1 、(40分)堆排序

堆排序的思想實際上利用完全二叉樹存儲在數組中,通過調整完全二叉樹成爲大頂堆獲得一個排序表的最大值進行排序的方法,大頂堆滿足根節點比子樹旳節點大。堆排序主要是通過大頂堆旳根元素與未完成排序旳最後一個元素進行交換,將交換後旳完全二叉樹不滿足大頂堆要求調整到滿足滿足要求,調整通過如下方法完成:
 void heapAdjust(int[] R,int s,int t);

其中,數組R中存儲旳二叉樹,只有以R[s]爲根子樹,其左右子樹之間可能不滿足大頂堆特徵。調整堆旳操作難點爲根子樹節點編號爲i,則左子樹節點編號爲2*i,右子樹節點編號爲2*i+1;通過比較子樹旳大小選擇大旳子樹進行調整,一直調整到根節點比子節點大,再將根節點旳值插入到最後調整旳節點。要完成堆排序,在調整旳基礎上可以通過從堆底往堆頂進行調整獲得初始堆,然後通過N-1次調整完成排序,控制流程爲:
 void heapSort(int[] R){
   int i;
   int N=R.length-1;
   for(i=N/2;i>0;i--){
     heapAdjust(R,i,N);
   }
   for(i=N;i>1;i--){
     R[0]=R[1];R[1]=R[i];R[i]=R[0];
     heapAdjust(R,1,i-1);
   }
 }
 給你旳問題是,將標準輸入的n個整數採用堆排序,並需要顯示建成旳初始堆,並完成該數據的排序。
輸入:標準輸入,輸入的第一行爲整數的個數n值,第二行爲n個整數,每個整數之間爲一個空格。
輸出:標準輸出,第一行依次輸出排序過程中建成旳初始堆在數組中的存儲值,每個輸出數據之間使用一個空格隔開,第二行輸出排序後的序列,每個輸出數據之間使用一個空格隔開。
輸入樣例:
14
39 80 76 41 13 29 50 78 30 11 100 7 41 86
輸出樣例:
100 80 86 78 39 41 76 41 30 11 13 7 29 50
7 11 13 29 30 39 41 41 50 76 78 80 86 100

 

 


import java.util.Scanner;

public class Heapsort {
	public static void main(String[] args) {
		int n;int[] data;
		Scanner in=new Scanner(System.in);
		n=in.nextInt();
		data=new int[n];
		for(int i=0;i<n;i++)
			data[i]=in.nextInt();
		heapSort(data,0,data.length-1);
		for(int i=0;i<n;i++)
			System.out.print(i!=n-1?data[i]+" ":data[i]);
		System.out.println();
	}
	public static void heapSort(int[] data,int low,int high){
		int i,top;
        int N=data.length-1;
        for(i=N/2;i>=0;i--){//創建初始堆
             siftdown(data,i,N);
        }
        for(i=0;i<=N;i++)
			System.out.print(i!=N?data[i]+" ":data[i]);	
        System.out.println();
        for(i=N;i>0;i--){
        	//取出堆頂元素放在數組的最後面,數組最後的數放在堆頂再向下調整,數組的0位置不用來存儲堆數據,用來交換數據的時候暫存數據
             top=data[0];
             data[0]=data[i];
             data[i]=top;       
             siftdown(data,0,i-1);
        }

	}
    public static void siftdown(int[] data,int low,int high){
    	int k=low;
    	int j=2*k+1;
    	int temp=data[k];
    	while(j<=high){
    		 //判斷右子節點是否存在,並比較左右節點的大小,和最大的交換
    		 if((j<high)&&(j+1<=high)&&(data[j]<data[j+1])) 
    			 ++j;
    		 if(temp<data[j]){//調整完之後繼續向下調整
    			  data[k]=data[j];
    			  k=j;
    			  j=2*k+1;
    		 }else{
    			 break;
    		 }
    	}
    	data[k]=temp;//找到該點的合適位置
    }
}


2 、(30分)希爾排序

希爾排序的思想是:先選擇一個小於排序數據個數n的整數di(稱爲步長,一般爲小於n的質數),將間隔di的數爲一組,對每組的元素進行直接插入排序,即將需要排序的數據插入到已經排序好攏到序列中。當步長爲1時,完成整個數據的排序。排序的流程爲:
    1、根據步長的個數,對於每個步長進行分組;
    2、對每組進行插入排序,主要操作如下:
          1)如果未有存在未有序的數據,將該數據存儲到臨時遍歷R[0]中;
          2)將前面比他大的數據全部向後移動一位;
          3)再將R[0]的數據插入到最後移動到數據位置;
  給你到問題是,將標準輸入的n個整數採用希爾排序,步長取5,3,1,並需要顯示出每次需要插入的數,並完成該數據的排序。
輸入:標準輸入,輸入的第一行爲整數的個數n值,第二行爲n個整數,每個整數之       間爲一個空格。
輸出:標準輸出,輸出第一行依次輸出排序過程中需要插入的數,每個輸出數據之間使用一個空格隔開,第二行輸出排序後的序列,每個輸出數據之間使用一個空格隔開。
輸入樣例:
14
39 80 76 41 13 29 50 78 30 11 100 7 41 86
輸出樣例:
29 50 30 11 7 41 39 13 86 7 29 11 30 41 50 80 78
7 11 13 29 30 39 41 41 50 76 78 80 86 100

 

 

import java.util.Scanner;


public class ShellSort {
	public static void main(String[] args) {
        int[] data;
        int[] d={5,3,1};
        int n;
        Scanner in=new Scanner(System.in);
        n=in.nextInt();
        data=new int[n];
        for(int i=0;i<n;i++)data[i]=in.nextInt();
        shellsort(data,d);
        for(int i=0;i<n;i++)
        	System.out.print(data[i]+" ");
        System.out.println();
	}
	public static void shellsort(int[] data,int[] d){
		int h,temp,k,j,p;
		for(k=0;k<3;k++){
			h=d[k];
			for(j=h;j<data.length;j++){
				if(data[j]<data[j-h]){
					temp=data[j];
					System.out.print(data[j]+" ");
					for(p=j;p>=h&&temp<data[p-h];p=p-h){
						data[p]=data[p-h];
					}
					data[p]=temp;
				}
			}	
		}
	    System.out.println();
	}

}

 

3 、(30分)快速排序

        快速排序的核心操作是劃分,通過某個數據將原來排序表分成兩部分,前面部分比該數小,後面數據比該數據大或相等,該數據就爲排序後的位置,即該數據完成排序。如果定義一個排序表的劃分方法爲:      int partition(int[] R,int low,inthigh);     其中,low,high表示將數據R的第low個數據到high個數據進行劃分,返回到整數爲劃分後到支點記錄位置;定義完成劃分方法後,通過如下調用完成快速排序:

 voidQuickSort(int[] R,int s,int t){if(s<t){             i=partition(R,s,t);             QuickSort(R,s,i-1);              QuickSort(R,i+1,t);         }     }     建議每次劃分選擇第一個元素爲支點記錄進行編程。給你到問題是,將標準輸入的n個整數採用快速排序,並需要顯示出每次劃分所使用到分支點記錄,並完成該數據的排序。輸入:標準輸入,輸入的第一行爲整數的個數n值,第二行爲n個整數,每個整數之間爲一個空格。輸出:標準輸出,輸出的第一行依次輸出排序過程中使用的支點記錄,每個輸出數據之間使用一個空格隔開,第二行輸出排序後的序列,每個輸出數據之間使用一個空格隔開。輸入樣例:1439 8076 41 13 29 50 78 30 11 100 7 41 86輸出樣例:39 7 11 30 1350 41 76 100 86 78 7 11 13 29 30 39 41 41 50 76 78 80 86 100

 

import java.util.Scanner;

public class Quicksort {
	public static void main(String[] args) {
		int n;int[] data;
		Scanner in=new Scanner(System.in);
		n=in.nextInt();
		data=new int[n];
		for(int i=0;i<n;i++)
			data[i]=in.nextInt();
		QuickSort(data,0,data.length-1);
		System.out.println();
		for(int i=0;i<n;i++)
			System.out.print(data[i]+" ");
		System.out.println();
			

	}
	public static void QuickSort(int[] R,int low,int high){
		int base=R[low];
		System.out.println(R[low]+" ");
		int i=low+1;
		int j=high;
		int temp;
		while(i<j){
			while((i<j)&&(R[i]<=base))
				++i;
			while((i<j)&&(R[j]>=base))
				--j;
			if(i<j){
				temp=R[i];
				R[i]=R[j];
				R[j]=temp;
			}
		}
		if(R[j]<R[low]){
			temp=R[low];
			R[low]=R[j];
			R[j]=temp;
		}
		System.out.println();
		if(i-low>1)
			QuickSort(R,low,i-1);
		if(high-j>1)
			QuickSort(R,j,high);
	}
}
/*解決當數組不發生交換時有一個未排序的數字被剔除的問題
1 加一個判斷當元素大於兩個又不發生交換的時候 剔除基數
if(i==low+1&&R[i]>R[low]){
   i=low;
   j=low;
}
2 把調整位置的點也就是兩個指針共同指向的點調進大於基數的分組中
if(high-j>1)
   QuickSort(R,j,high);
*/


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