一:插入排序
二:選擇排序
三:交換排序
四:歸併排序
五:基數排序
插入排序:(直接插入排序,shell排序)
1:直接插入排序
把左邊作爲已經排序好的數組,新加入的數組值和左邊的數組最右邊數值比較,直到不大於左邊的數時停止,循環完成。最優的時間複雜度爲O(n),最大時間複雜度爲O(n^2),平均時間複雜度爲O(n^2),是穩定的算法。
java實現代碼:
package com.hdw.sort;
public class InsertSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {9,2,7,6,4,8,1,3,5};
insertSort(a);
print(a);
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
}
private static void insertSort(int[] a) {
// TODO Auto-generated method stub
for(int i=1; i<a.length; i++){
int temp;
for(int j=i; j>=1; j--){
if(a[j]<a[j-1]){
temp = a[j];
a[j] = a[j-1];
a[j-1] = temp;
}else{
break;
}
}
}
}
}
2:shell排序
是對於直接插入排序的優化,shell排序中d的選取很重要,不同的時代的人對於d的選取有不同的看法,有d=2*n-1、d=3*n+1、d=5n-1,但是不管怎麼選,d=1,必須要存在,這保證了排序的正確性,她的妙處在於把相鄰d的數排序好,改進了對於d=1的壓力,最優時間複雜度爲O(n),最壞時間複雜度爲O(n^2),平均時間複雜度爲O(n^1.3),這個1.3是科學家算出來的,爲不穩定算法。
java代碼實現
package com.hdw.sort;
public class ShellSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {9,2,7,6,4,8,1,3,5};
print(a);
shellSort(a);
print(a);
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
System.out.println();
}
private static void shellSort(int[] a) {
// TODO Auto-generated method stub
//第一層循環是對於d的選取
for(int d=a.length/2; d>0; d/=2){
//第二層循環是讓第d個數後的每一個數和前面相差d的數做插入排序
for(int i=d; i<a.length; i++){
int temp;
//相差d的數做插入排序
for(int j=i; j>=d; j-=d){
if(a[j]<a[j-d]){
temp = a[j];
a[j] = a[j-d];
a[j-d] = temp;
}else{
break;
}
}
}
print(a);
}
}
}
選擇排序:(直接選擇排序,堆排序)
1:直接選擇排序
把數組中最大(最小)的值,選出放在數組的開頭,後面有從2到n中選出最大(最小)數放到小標爲2的數中,最優,最壞,平均時間複雜度均爲O(n^2),不穩定算法
java代碼實現
package com.hdw.sort;
public class SelectSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {9,2,7,6,4,8,1,3,5};
selectSort(a);
print(a);
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
}
private static void selectSort(int[] a) {
// TODO Auto-generated method stub
for(int i=0; i<a.length-1; i++){
int temp=a[i];
int flag = i;
for(int j=i+1; j<a.length; j++){
if(a[j]<temp){
temp = a[j];
flag = j;
}
}
a[flag] = a[i];
a[i] = temp;
}
}
}
2:堆排序
首先建立一個二叉樹,把數組想象成二叉樹,第一個步驟就是建立一個大頂推(小頂堆)的二叉樹,第二部就是把大頂推(小頂堆)放在數組最後面一位,接下來的數再建立大頂堆(小頂堆),循環結束,最優、最差、平均時間算法O(nlog2n),不穩定算法。
java代碼實現
package com.hdw.sort;
public class HeapSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {9,2,7,6,4,8,1,3,5};
heapSort(a);
print(a);
}
private static void heapSort(int[] a) {
// TODO Auto-generated method stub
for(int i=a.length-1; i>0; i--){
createMaxHeap(a,i);
swap(a,0,i);
}
}
private static void swap(int[] a, int i, int j) {
// TODO Auto-generated method stub
a[i] = a[i] + a[j];
a[j] = a[i] - a[j];
a[i] = a[i] - a[j];
}
private static void createMaxHeap(int[] a,int lastIndex) {
// TODO Auto-generated method stub
for(int i=(lastIndex-1)/2; i>=0; i--){
int k = i;
//對K下面的樹建立大頂推
while(2*k+1<=lastIndex){
//假使最大數的下標爲2*k+1
int maxIndex = 2*k+1;
//如果存在右子樹則比較,選擇較大數的下標,爲下面和父節點比較
if(maxIndex < lastIndex){
if(a[maxIndex] < a[maxIndex+1]){
maxIndex++;
}
}
//直接子節點和父節點比較,若需要交換則把k換爲最大子節點的下標,好向下遞推建立大頂推樹,否則直接退出while循環
if(a[k] < a[maxIndex]){
swap(a, k, maxIndex);
k = maxIndex;
}else{
break;
}
}
}
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
}
}
交換排序:
1:冒泡排序
相鄰兩個數進行比較把大的數放在右邊,循環後最大的數再數組的最右邊,對剩餘n-1個數使用同樣的方法,最優時間複雜度O(n),最差時間複雜度O(n^2),平均時間複雜度爲O(n^2),穩定算法。
java代碼實現
package com.hdw.sort;
public class BubbleSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//int[] a = {9,2,7,6,4,8,1,3,5};
int[] a = {1,2,3,4,5,6};
print(a);
bubbleSort(a);
print(a);
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
System.out.println();
}
private static void bubbleSort(int[] a) {
// TODO Auto-generated method stub
for(int i=0; i<a.length-1; i++){
boolean flag = false;
for(int j=0; j<a.length-1-i; j++){
int temp=a[j];
if(a[j]>a[j+1]){
a[j] = a[j+1];
a[j+1] = temp;
flag = true;
}
}
if(!flag){
break;
}
print(a);
}
}
}
2:快速排序
快速排序是對於冒泡排序的改進,把中間值作爲一個key,左邊放的是比key小的值,右邊是比key大的值,然後key左邊的數進行快排,右邊也進行快排,遞歸結束,最優時間複雜度爲O(nlog2n),最差時間複雜度爲O(n^2),平均時間複雜度爲O(nlog2n),不穩定算法
java代碼實現
package com.hdw.sort;
public class QuickSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {9,2,7,6,4,8,1,3,5};
print(a);
quickSort(a,0,a.length-1);
print(a);
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
System.out.println();
}
private static void quickSort(int[] a, int left,int right){
//當可以進行快排時
if(left < right){
//把最左邊的值設爲key,把left的值賦給low,right的值賦給high
int key = a[left];
int low = left;
int high = right;
//當low<high時,循環把比key更大的放在它右邊,比key更小的值放在它的左邊
while(low<high){
//如果右邊的值大於key則一直向後對比
while(low < high && a[high] >= key){
high--;
}
//符合是把高位的值賦給低位的值
a[low] = a[high];
//如果左邊的值一直小於key則一直向前對比
while(low < high && a[low] < key){
low++;
}
//把地位的值賦值給高位
a[high] = a[low];
}
//把key的值賦給指針停止的地方
a[low] = key;
quickSort(a,left,low-1);
quickSort(a,low+1,right);
}
}
}
歸併排序:
把數組每兩個進行比較,比較完了以後作爲一個整體,在兩個整體之間的比較,循環下去,直到結束,我採用的是遞歸算法,真個數組分爲兩個部分,左邊歸併,右邊也歸併,最優、最差、平均時間負雜度爲O(nlog2n),需要輔助空間爲O(n),穩定算法
java代碼實現
package com.hdw.sort;
public class MergeSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {9,2,7,6,4,8,1,3,5};
int[] temp = new int[a.length];
mergeSort(a,0,a.length-1,temp);
print(a);
}
private static void mergeSort(int[] a, int first, int last, int[] temp) {
// TODO Auto-generated method stub
if(first < last){
int mid = (first + last) / 2;
mergeSort(a,first,mid,temp);
mergeSort(a,mid+1,last,temp);
mergeArray(a,first,mid,last,temp);
}
}
private static void mergeArray(int[] a, int first, int mid, int last,
int[] temp) {
// TODO Auto-generated method stub
int i = first;
int j = mid + 1;
int m = mid;
int n = last;
int k = 0;
while(i <= m && j <= n){
if(a[i] < a[j]){
temp[k++] = a[i++];
}else{
temp[k++] = a[j++];
}
}
while(i <= m){
temp[k++] = a[i++];
}
while(j <= n){
temp[k++] = a[j++];
}
for(i = 0; i < k; i++){
a[first+i] = temp[i];
}
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
}
}
基數排序:
d爲數組的最大位數,r爲可區分每個數的基數的位數,比如數組裏面的是整數則r=9,範圍0-9,英文字母則爲26,a-z,先把個位數排序,放在一個輔助的數組空間裏,在把輔助空間裏面值賦值給原數組,接着是百位數排序,重複,知道所有位數排序完,如果位數r比較大時,則從高位開始排序,最優時間複雜度爲O(d(r+n)),最差時間複雜度爲O(d(n+rd)),平均O(d(r+n)),需要輔助空間O(rd+n)
java代碼實現
package com.hdw.sort;
import java.util.Arrays;
public class RadixSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {1100, 192, 221, 12, 23};
print(a);
radixSort(a,10,4);
print(a);
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
System.out.println();
}
/********************************************************
*函數名稱:radixSort
*參數說明:需要排序的數組
* radix表示 基數的大小
* distance表示最高位數的大小
*說明: 通過基數排序把數組排好
*********************************************************/
private static void radixSort(int[] a, int radix, int distance) {
// TODO Auto-generated method stub
//緩存數組
int[] temp = new int[a.length];
//存儲不同小標的個數
int[] count = new int[radix];
//設置每次求數組數除於的數
int rate = 1;
//把每一個位數的數比較
for(int i=0; i<distance; i++){
//把數組a的值賦值給temp數組
System.arraycopy(a, 0, temp, 0, a.length);
//初始化數組count每個值爲0
Arrays.fill(count, 0);
//統計小標爲key的值的個數
for(int j=0; j<a.length; j++){
int key = (temp[j]/rate)%radix;
count[key]++;
}
//對count的值進行相加,這裏j是小於radix,不是a.length
for(int j=1; j<radix; j++){
count[j] += count[j-1];
}
//進行數組的交換
for(int m=a.length-1; m>=0; m--){
int subkey = (temp[m]/rate)%radix;
count[subkey]--;
a[count[subkey]] = temp[m];
}
//對下面一個位數排序
rate*=radix;
print(a);
}
}
}