各種排序演算法大合集
阿新 • • 發佈:2018-12-18
各種演算法的比較: 快速排序:
希爾(Shell)排序: 要點 希爾(Shell)排序又稱為縮小增量排序,它是一種插入排序。它是直接插入排序演算法的一種威力加強版。
希爾排序的基本思想是:
把記錄按步長 gap 分組,對每組記錄採用直接插入排序方法進行排序。 隨著步長逐漸減小,所分成的組包含的記錄越來越多,當步長的值減小到 1 時,整個資料合成為一組,構成一組有序記錄,則完成排序。
我們來通過演示圖,更深入的理解一下這個過程。
在上面這幅圖中:
初始時,有一個大小為 10的無序序列。
在第一趟排序中,我們不妨設 gap1 = N / 2 = 5,即相隔距離為 5 的元素組成一組,可以分為 5 組。
接下來,按照直接插入排序的方法對每個組進行排序。
在第二趟排序中,我們把上次的 gap縮小一半,即 gap2 = gap1 / 2 = 2 (取整數)。這樣每相隔距離為 2的元素組成一組,可以分為 2 組。
按照直接插入排序的方法對每個組進行排序。
在第三趟排序中,再次把 gap縮小一半,即gap3 = gap2 / 2 = 1。這樣相隔距離為 1 的元素組成一組,即只有一組。
按照直接插入排序的方法對每個組進行排序。此時,排序已經結束。
需要注意一下的是,圖中有兩個相等數值的元素 5 和 5 。我們可以清楚的看到,在排序過程中,兩個元素位置交換了。
所以,希爾排序是不穩定的演算法。
朕的實現方法在此:
//測試類: //注意:com.sxt.xxx 是包名 package org.sxt.test; import java.util.Arrays; import java.util.Scanner; import com.sxt.b.BubbleSort; import com.sxt.b.InsertSort; import com.sxt.b.MergeSort; import com.sxt.b.QuickSort; import com.sxt.b.SelectSort; import com.sxt.b.ShellSort; import com.sxt.win.Show; public class TestSort { public static void main(String[] args) { //1.給出無序陣列 int arr[]= {72,6,57,88,60,42,83,73,48,85}; //2.輸出無序陣列 System.out.println("原陣列:"+Arrays.toString(arr)); while(true) { //3.排序 Show.show(); Scanner sc = new Scanner(System.in); int select = sc.nextInt(); switch(select) { case 1:QuickSort.quickSort(arr);break; case 2:BubbleSort.bulleSort(arr);break; case 3:SelectSort.select(arr);break; case 4:InsertSort.insertSort(arr);break; case 5:ShellSort.shellSort(arr);break; case 6:MergeSort.merge_sort(arr);break; } //4.輸出有序數列 System.out.println(Arrays.toString(arr)); } } }
package com.sxt.win;
public class Show {
public static void show() {
System.out.println("請選擇排序方式:\n1.快速排序\n2.氣泡排序\n3.選擇排序\n4.插入排序\n5.希爾遍歷\n6.歸併排序");
}
}
//氣泡排序
package com.sxt.b;
public class BubbleSort {
//氣泡排序演算法
public static void bulleSort(int[] arr) {
for(int i=0;i<arr.length-1;i++)//掃描次數
{
for(int j=0;j<arr.length-1-i;j++) {
if(arr[j]>arr[j+1]) {
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
}
//插入排序
package com.sxt.b;
public class InsertSort {
public static void insertSort(int[] arr) {
/*遍歷所有的數字看哪個比前面的小,
*如果小那就說明前面至少有一個比當前元素小的
*把當前元素塞到剛好比當前元素的小的元素前面,那麼它後邊的都要往後排一個
*/
for(int i=1;i<arr.length;i++) {
//如果當前數字比前一個數字小
if(arr[i]<arr[i-1]) {
//先把當前元素存起來
int temp=arr[i];
//遍歷當前元素前面的元素
for(int j=i-1;j>0&&temp<arr[j];j--) {
//把前一個數字賦給後一個數字
arr[j+1]=temp;
}
}
}
}
}
//歸併排序
package com.sxt.b;
public class MergeSort {
public static void merge_sort(int[] arr) {
mergesort(arr, 0, arr.length - 1);
}
public static void mergesort(int[] arr,int left, int right) {
if(left < right) return;
int middle = (left+right) / 2;
mergesort(arr, left, middle);
mergesort(arr, middle + 1, right);
mergeArr(arr, left, middle, right);//將左右兩部分合並(左右兩部分已經在遞迴中各自排好了序)
}
public static void mergeArr(int[] arr, int left, int middle, int right) {
int[] temp = new int[right - left + 1];//開闢新陣列
int i = left, j = middle + 1, k = 0;
while(i <= middle && j <= right) {//經過這個迴圈後最多有一個數組有殘餘
temp[k++] = arr[i] < arr[j]? arr[i++] : arr[j++];
}
while(i <= middle) {//如果有殘餘加入到temp中
temp[k++] = arr[i++];
}
while(j <= right) {//如果有殘餘加入到temp中
temp[k++] = arr[j++];
}
// 將輔助陣列資料寫入原陣列
int index = 0;
while(left <= right) {
arr[left++] = temp[index++];
}
}
}
//快速排序
package com.sxt.b;
public class QuickSort {
//分割槽函式
private static int partition(int[] arr,int low,int high) {
//1.指定左指標i和右針織j
int i=low;
int j=high;
//2.將第一個元素作為基準,挖坑帶走
int x=arr[low];
//3.使用迴圈實現分割槽操作
while(i<j) {
//1.從右至左移動j,找到第一個小於基準值的元素,arr[j],挖走
while(arr[j]>x&&i<j) {
j--;
}
//2.將arr[j]填入左邊坑的位置,左指標i向右移動一個單位,指標右移一位i++
if(i<j) {
arr[i]=arr[j];
i++;
}
//3.從左向右移動i,找到第一個大於基準的元素arr[i]
while(arr[i]<x&&i<j) {
i++;
}
//4.將左側找到的元素填入到右邊的坑內,j--
if(i<j) {
arr[j]=arr[i];
j--;
}
}
//4.使用基準填坑,這是基準值的最終位置
arr[i]=x;
//5.返回基準的位置、
return i;
}
//快速排序演算法
private static void quickSort(int[] arr,int low, int high) {//遞迴何時結束(low<high),所剩元素大於兩個
if(low<high) {
//分割槽操作,將一個數組分成兩個分割槽,並返回分割槽索引
int index=partition(arr,low,high);
//將左分割槽進行快排
quickSort(arr,low,index-1);
//將右分割槽進行快排
quickSort(arr,index+1,high);
}
}
public static void quickSort(int[] arr) {
int low=0;
int high=arr.length-1;
quickSort(arr,low,high);
}
}
//選擇排序
package com.sxt.b;
public class SelectSort {
public static void select(int[] arr) {
for(int i=0;i<arr.length-1;i++)
for(int j=i+1;j<arr.length;j++)
{
if(arr[i]>arr[j])
{
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
}
//希爾排序
package com.sxt.b;
import java.util.Arrays;
public class ShellSort {
public static void shellSort(int[] arr) {
int k=0;
//遍歷所有的步長(步長每次減半)
for(int d=arr.length/2;d>0;d/=2)
{
//遍歷所有組
for(int i=d;i<arr.length;i++) {
//遍歷本組中的元素(相隔為d的元素是一組)
for(int j=i-d;j>=0;j-=d)
{
//如果當前元素大於加上步長後的元素則交換位置
if(arr[j]>arr[j+d]) {
int temp=arr[j];
arr[j]=arr[j+d];
arr[j+d]=temp;
}
}
}
k++;
System.out.println("第"+k+"次步長折半遍歷"+Arrays.toString(arr));
}
}
}