1. 程式人生 > >Java高頻演算法--排序、查詢總結

Java高頻演算法--排序、查詢總結

排序

查詢

氣泡排序

對於給定的n個記錄,從最後一個記錄開始依次對相鄰的兩個記錄進行比較,當後面的記錄小於前面的記錄時,交換位置,進行一輪比較和換位後,n個記錄中最小記錄將位於第1位;然後對後(n-1)個記錄進行第二輪比較;重複該過程直到進行比較的記錄只剩下一個為止。

public class Solution1 {
	//氣泡排序
	public static void BubbleSort(int array[]) {
		int len=array.length;
		if(array==null||len<=0)
			return;
		for(int i=0;i<len-1;i++)//一共輪迴比較len-1次
			for(int j=len-1;j>i;j--)    //從後往前
				if(array[j]<array[j-1]){//把最小的放在當前陣列的第一個位置
					int tmp = array[j];
					array[j]=array[j-1];
					array[j-1]=tmp;
				}		
	}
	public static void main(String[] args) {
		int []a= {3,5,2,7,3,9,1};
		Solution1.BubbleSort(a);
		System.out.print("排序後的陣列為:");
        for(int i=0;i<a.length;i++){
        	System.out.print(a[i]+",");
        }
	}
}

快速排序

是一種非常高效的排序演算法,“分而治之”。它的基本思想是:通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,然後再按此方法對這兩部分資料分別進行快速排序,整個排序過程可以遞迴進行,以此達到整個資料變成有序序列。一趟快速排序的演算法是:

1)設定兩個變數i、j,排序開始的時候:i=0,j=N-1;

2)以第一個陣列元素作為關鍵資料,賦值給key,即key=A[0];

3)從j開始向前搜尋,即由後開始向前搜尋(j--),找到第一個小於key的值A[j],將A[j]和A[i]互換;

4)從i開始向後搜尋,即由前開始向後搜尋(i++),找到第一個大於key的A[i],將A[i]和A[j]互換;

5)重複第3、4步,直到i=j; (3,4步中,沒找到符合條件的值,即3中A[j]不小於key,4中A[i]不大於key的時候改變j、i的值,使得j=j-1,i=i+1,直至找到為止。找到符合條件的值,進行交換的時候i, j指標位置不變。另外,i==j這一過程一定正好是i+或j-完成的時候,此時令迴圈結束)

public class Solution2 {
	//快速排序
	  public static void QuickSort(int array[]){
		  Sort(array,0,array.length-1);
	  }
	  public static void Sort(int a[],int low,int high){
		  int i,j;
		  if (low>=high)return;
		  int index;
		  i=low;
		  j=high;
		  index=a[i];
		  while(i<j){
			  while(i<j&&a[j]>=index)
				  j--;
			  if(i<j) {
				  a[i]=a[j];
				  i++;
			  }
			  while(i<j&&a[i]<index)
				  i++;
			  if(i<j) {
				  a[j]=a[i];
				j--;
			  }
		  }
		  a[i]=index;
		  Sort(a,low,i-1);
		  Sort(a,i+1,high);
	  }
	  public static void main(String[] args){
		  int a[]={3,9,2,4,8,6};
		  QuickSort(a);
		  for(int i=0;i<a.length;i++){
			  System.out.print(a[i]+",");
	      }
	  }
}

堆排序

是選擇排序的一種。可以利用陣列的特點快速定位指定索引的元素。堆分為大頂堆和小頂堆,是完全二叉樹。對於給定的n個記錄,初始時把這些記錄看作一棵順序儲存的二叉樹,然後將其調整為一個大頂堆,然後將堆的最後一個元素與堆頂元素交換,堆的最後一個元素即為最大記錄;接著將前(n-1)個元素(即不包括最大記錄)重新調整為一個大頂堆,再將堆頂元素與當前堆的最後一個元素進行交換得到次大的記錄;重複該過程直至調整的堆中只剩下一個元素時為止,該記錄即為最小記錄,此時可得到一個有序序列。

public class Solution3 {
	//堆排序
  public static void adjustMinHeap(int a[],int pos,int len){
	  int temp;
	  int child;
	  for(temp=a[pos];2*pos+1<=len;pos=child){
		  child=2*pos+1;
		  if(child<len&&a[child]>a[child+1]) 
			  child++;
		  if(a[child]<temp) 
			  a[pos]=a[child];
		  else break;
	  }
	  a[pos]=temp;
  }
  public static void myMinHeapSort(int array[]){
	  int i;
	  int len=array.length;
	  for(i=len/2-1;i>=0;i--)
		  adjustMinHeap(array,i,len-1);
	  for(i=len-1;i>=0;i--){
		  int tmp=array[0];
		  array[0]=array[i];
		  array[i]=tmp;
		  adjustMinHeap(array,0,i-1);
	  }
  }
  public static void main(String[] args){
	  int a[]={3,9,8,4,2,1};
	  myMinHeapSort(a);
	  for(int i=0;i<a.length;i++){
              System.out.print(a[i]+",");
	  }
  }
}

插入排序

對於給定的一組記錄,初始時假設第一個記錄自成一個有序序列,其餘記錄為無序序列。接著從第二個記錄開始,按照記錄的大小依次將當前處理的記錄插入到其之前的有序序列中,直至最後一個記錄插入到有序序列中為止。

public class Solution4 {
	//插入排序
  public static void insertSort(int a[]){
	  if(a!=null){
		  for(int i=1;i<a.length;i++){
			  int temp=a[i],j=i;  //a[i]表示將要進行插入操作的元素。
			  if(a[j-1]>temp){   //a[j-1]為前面排序好部分的最後一個元素。
				  while(j>=1&&a[j-1]>temp){
					  a[j]=a[j-1];
					  j--;
				  }
			  }
			  a[j]=temp;
		  }
	  }
  }
  public static void main(String[] args){
	  int a[]={3,9,8,4,2,1};
	  insertSort(a);
	  for(int i=0;i<a.length;i++){
          	System.out.print(a[i]+",");
	  }
  }
}

選擇排序

對於給定的一組記錄,經過第一輪比較後得到最小的記錄,然後將該記錄與第一個記錄的位置進行交換;接著對不包括第一個記錄的其他記錄進行第二輪比較,得到最小的記錄並與第二個位置交換;重複該過程,直到進行比較的記錄只有一個時為止。

public class SelectSort {
  public static void selectSort(int [] a){
	  int i,j;
	  int temp=0;
	  int flag=0;
	  int len=a.length;
	  for(i=0;i<len;i++){
		  temp=a[i];
		  flag=i;
		  for(j=i+1;j<len;j++){
			  if (a[j]<temp){ 
				  temp=a[j];   //找出最小值,賦值給temp;
				  flag=j;      //儲存最小值的下標
			  }
		  }
		  if(flag!=i){          //i不是當前最小值的下標
			  a[flag]=a[i];     
			  a[i]=temp;        //將最小的記錄與a[i]交換。
		  }
	  }
  }
  public static void main(String[] args){
	  int a[]={3,9,2,4,8,6};
	  selectSort(a);
	  for(int i=0;i<a.length;i++){
              System.out.print(a[i]+","); 
	  }
  }
}

希爾排序

插入排序的一種。也稱縮小增量排序,是直接插入排序演算法的一種更高效的改進版本。希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序演算法排序;隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個檔案恰被分成一組,演算法便終止。先取一個小於n的整數d1作為第一個增量,把檔案的全部記錄分組。所有距離為d1的倍數的記錄放在同一個組中。先在各組內進行直接插入排序;然後,取第二個增量d2<d1重複上述的分組和排序,直至所取的增量=1(<  …<d2<d1),即所有記錄放在同一組中進行直接插入排序為止。

public class Shell {
  public static void ShellSort(int array[]){
	  int len=array.length;
	  int i,j;
	  int h;
	  int temp;
	  for(h=len/2;h>0;h=h/2){
		  for(i=h;i<len;i++){
			  temp=array[i];
			  for(j=i-h;j>=0;j-=h){
				  if(temp<array[j]){
					  array[j+h]=array[j];
				  }else break;
			  }
			  array[j+h]=temp;
		  }
	  }
  }
  public static void main(String[] args){
	  int a[]={3,9,2,4,8,6};
	  ShellSort(a);
	  for(int i=0;i<a.length;i++){
              System.out.print(a[i]+","); 
	  }
  }
}

歸併排序

利用遞迴和分治技術。對於給定的n個記錄,首先將每兩個相鄰的長度為1的子序列進行歸併,得到n/2(向上取整)個長度為2或1的有序子序列,再將其兩兩歸併,反覆執行此過程,直到得到一個有序序列。

import java.util.Arrays;
public class MergeSort {
	 public static void merge(int[] a, int low, int mid, int high) {
	        int[] temp = new int[high - low + 1];
	        int i = low;        // 左指標
	        int j = mid + 1;    // 右指標
	        int k = 0;
	        // 把較小的數先移到新陣列中
	        while (i <= mid && j <= high) {
	            if (a[i] < a[j]) {
	                temp[k++] = a[i++];
	            } else {
	                temp[k++] = a[j++];
	            }
	        }
	        // 把左邊剩餘的數移入陣列
	        while (i <= mid) {
	            temp[k++] = a[i++];
	        }
	        // 把右邊邊剩餘的數移入陣列
	        while (j <= high) {
	            temp[k++] = a[j++];
	        }
	        // 把新陣列中的數覆蓋nums陣列
	        for (int k2 = 0; k2 < temp.length; k2++) {
	            a[k2 + low] = temp[k2];
	        }
	    }

	    public static void mergeSort(int[] a, int low, int high) {
	        int mid = (low + high) / 2;
	        if (low < high) { 
	            mergeSort(a, low, mid); // 左邊 
	            mergeSort(a, mid + 1, high);  // 右邊
	            merge(a, low, mid, high);  // 左右歸併
	        }
	    }
	    public static void main(String[] args) {
	        int a[] = { 51, 46, 20, 18, 65, 97, 82, 30, 77, 50 };
	        mergeSort(a, 0, a.length - 1);
	        System.out.println("排序結果:" + Arrays.toString(a));
	    }
}

二分查詢

又稱折半查詢,優點是比較次數少,查詢速度快,平均效能好;其缺點是要求待查表為有序表,且插入刪除困難。因此,折半查詢方法適用於不經常變動而查詢頻繁的有序列表。二分查詢的基本思想是將n個元素分成大致相等的兩部分,取a[n/2]與x做比較,如果x=a[n/2],則找到x,演算法中止;如果x<a[n/2],則只要在陣列a的左半部分繼續搜尋x,如果x>a[n/2],則只要在陣列a的右半部搜尋x.

public class BinarySearch {
	public static int sort(int []array,int index,int low,int high){
        if(low<=high){
            int mid=(low+high)/2;
            if(index==array[mid]){
                return mid; //求目標元素的下標
            }
            else if(index>array[mid]){
                return sort(array,index,mid+1,high);
            }else{
                return sort(array,index,low,mid-1);
            }
        }
        return -1;
    }
	public static void main(String[] args){
		int a[]={1,3,4,5,6,7,8,10,34};
		System.out.println(sort(a,10,0,a.length-1));
	}
}

程式碼粘進程式碼框,格式有些問題,調整不了,逼死強迫症啊!啊!啊!!!