排序算法根據不同的算法思想往往有很多不同的實現。近期,個人整理了常見的七種算法,並用java對各個算法進行了具體實現,包括:插入排序、冒泡排序、選擇排序、shell排序、歸併排序、快速排序以及堆排序。
一、插入排序
算法步驟:
從第二個數值開始依次往後遍歷。將第k個數值放到前面已經排好序的k-1個數值的合適位置。所謂的合適位置(以從小到大排序爲例)就是該位置的前一個數值小於number[k],而後一個位置的數值大於number[k]。
移動方法,依次比較k-1到0的所有數值,如果number[k]小於它前一個位置的數,就交換兩個數的位置。
過程示例:
核心代碼:
//插入排序
public static int[] insertSort(int[] number){
for(int i=1;i<number.length;i++){
int processPosition=i;
for(int j=i-1;j>=0;j--){
if(number[processPosition]<number[j]){
int temp=number[processPosition];
number[processPosition]=number[j];
number[j]=temp;
processPosition=j;
}
else break;
}
}
return number;
}
二、冒泡排序
算法步驟:
總共進行n-1趟(n爲數組長度)。每一趟都能取出未排序序列中的最小值,然後放到未排序序列的最前面,也就是第k趟取出的是整個序列中第k小的值。
移動方法,從最後一個數往前移動,比較相鄰兩個位置上數的大小,如果number[k]小於number[k-1],就交換兩個數值的位置。
過程示例:
核心代碼:
//冒泡排序
public static int[] bubblingSort(int[] number){
for(int i=0;i<number.length;i++){
for(int j=number.length-1;j>i;j--){
if(number[j]<number[j-1]){
int temp=number[j];
number[j]=number[j-1];
number[j-1]=temp;
}
}
}
return number;
}
三、選擇排序
算法過程:
過程和冒泡排序差不多,只不過它只做最後的那次交換。
過程示例:
核心代碼:
//選擇排序
public static int[] chooseSort(int[] number){
for(int i=0;i<number.length;i++){
int minValuePosition=number.length-1;
for(int j=number.length-2;j>=i;j--){
if(number[minValuePosition]>number[j]){
minValuePosition=j;
}
}
int temp=number[i];
number[i]=number[minValuePosition];
number[minValuePosition]=temp;
}
return number;
}
四、shell排序
算法步驟:
選擇一個初始增量,對距離爲該增量的數值序列進行插入排序。不斷縮小增量,不斷進行插入排序。直到增量爲1,最後進行一次排序後終止,即可得到結果。
過程示例:
核心代碼:
//shell排序
public static int[] shellSort(int[] number){
//選擇增量
for(int i=number.length/2;i>=1;i=i/2){
for(int j=0;j<i;j++){
insSort(number,j,i);
}
}
return number;
}
//shell排序中的插入排序
private static int[] insSort(int[] number,int start, int inc) {
for(int i=start;i<number.length;i+=inc){
int processPosition=i;
for(int j=i-1;j>=start;j-=inc){
if(number[processPosition]<number[j]){
int temp=number[j];
number[j]=number[processPosition];
number[processPosition]=temp;
processPosition=j;
}
else break;
}
}
return number;
}
五、歸併排序
算法步驟:
基於二分法的思想,每次都把待排序列劃分爲兩個部分,對兩個部分進行排序。運行遞歸不斷縮小待排序列的規模,終止條件爲待排序列大小爲1時。當兩個部分已排好序時,對其進行合併,依次比較兩個部分的最小值,取出更小的數值存入臨時數組中。
過程示例:
核心代碼:
//歸併排序
public static void mergeSort(int[] number,int start,int len){
if(len==1) return;
int half=start+len/2-1;
mergeSort(number,start,len/2);
mergeSort(number,half+1,len/2);
merge(number,start,len);
}
//歸併排序的數組合並函數
private static void merge(int[] number, int start, int len) {
System.out.println("合併後的數組:"+start+" "+len);
int leftstart=start;
int leftend=start+len/2-1;
int rightstart=start+len/2;
int rightend=start+len-1;
int[] temp=new int[len];
int position=0;
while(position<temp.length){
if((leftstart<=leftend)&&(rightstart<=rightend)){
if(number[leftstart]<number[rightstart]){
temp[position]=number[leftstart];
position++;
leftstart++;
}
else{
temp[position]=number[rightstart];
position++;
rightstart++;
}
}
else if(leftstart>leftend){
for(int i=rightstart;i<=rightend;i++){
temp[position]=number[i];
position++;
}
break;
}
else if(rightstart>rightend){
for(int i=leftstart;i<=leftend;i++){
temp[position]=number[i];
position++;
}
break;
}
}
for(int i=0;i<len;i++){
number[start+i]=temp[i];
}
}
六、快速排序
算法思想:
確定一個軸值。把在軸值左邊並且比它大的數據放到它的右邊,把在軸值右邊並且比它小的數據放到左邊。
過程示例:
核心代碼:
//快速排序
public static void qSort(int[] number,int start,int end){
if(end<=start) return;
int devided=partition(number,start,end);
qSort(number,start,devided-1);
qSort(number,devided+1,end);
}
//排序的核心代碼
private static int partition(int[] number, int start, int end) {
int half=(end-start)/2+start;
int l=start,r=end;
while(l<r){
while((number[l]<=number[half])&&(l<end)){
l++;
}
while((r>l)&&(number[r]>=number[half])) r--;
swap(number,l,r);
}
if(((l<half)&&(number[l]>number[half]))||((l>half)&&(number[l]<number[half]))){
//改變軸值的位置
swap(number,l,half);
}
return l;
}
//交換函數
private static void swap(int[] number, int i, int j) {
int temp=number[i];
number[i]=number[j];
number[j]=temp;
}
七、堆排序
堆排序由於需要建樹,比較複雜。這裏只給我的測試代碼,堆的構建和具體的算法思想可以看我的另一篇博客:《堆的實現(數據結構)》
測試代碼:
//測試代碼
ArrayList<Node>nodeList=new ArrayList();
nodeList.add(new Node(1,"A"));
nodeList.add(new Node(9,"B"));
nodeList.add(new Node(3,"C"));
nodeList.add(new Node(6,"D"));
nodeList.add(new Node(7,"E"));
Heap heap=new Heap(nodeList);
heap.buildHeap();
System.out.println("當前的堆結構");
for(int i=0;i<heap.length();i++){
System.out.println(heap.nodeList.get(i).key+"-"+heap.nodeList.get(i).value);
}
System.out.println("堆排序後的結果");
int max=heap.length();
for(int j=0;j<max;j++){
Node result=heap.removeFirst();
System.out.println(result.key+result.value);
}
整個程序完整的代碼較長,這裏就不放上來了,有需要的可以留言。