Java 排序(這里統一做從小到大排)
快速排序 ·
快速排序用分而治之的思想。對于要排序的數據,選取最左邊的作為基準,然后將比基準大的數放到其右邊,將比基準小的數放到其左邊,然后以基準位子進行分割,對其左右做分治遞歸操作。
int[] data;//待排序數組
//快速排序java代碼
public void quickSort(int[] data,int left,int right){
if(left<0||right>data.length) return;
if(left<right){
int i=left;
int j=right;
int base=data[i];
while(i<j){
while(i<j&&data[j]>base) j--;
if(i<j) data[i++]=data[j];
while(i<j&&data[i]<base) i++;
if(i<j) data[j--]=data[i];
}
data[i]=base;
quickSort(data,left,i-1);
quickSort(data,i+1,right);
}
}
快速排序可以理解成如下:
首先在最左邊挖一個坑 base=data[i]
然后從最右邊開始找一個比這個數小的值來填補這個坑data[i++]=data[j]
此時data[i] 這個坑被data[j] 填補了,現在坑變成了data[j]
然后從左邊開始尋找一個比base大的數來填坑 data[j--]=data[i]
不斷重復知道 i==j,此時跳出循環將最開始的base填入data[i] 中
這時候就形成了以位置i為分界點左邊全部比base小,右邊全部比base大的局面
最后遞歸這個過程就完成看排序
快速排序分析
快速排序復雜度 輔佐空間為O(1)
堆排序
堆排序的主要思想是不斷維護一個堆,在這里談從小到大排序的話就維護一個大頂堆,每次從堆頂取出一個元素(這個元素在堆中是最大的),然后與堆尾交換,之后堆大小減小1,重新調整堆。
要點如下
1 構造 初始化大頂堆
2 從堆頂取出元素與堆尾交換,堆大小減一
3 重新調整被破壞的堆
重復步驟2 直到堆大小為0 此時數組已經被從小到大排序完畢
堆這個數據結構特點:
- 父節點一定比左右子節點要大
- 堆在存儲時有數組存儲,父節點ID=i,那么左右子節點ID分別為 2i+1和 2i+2
最開始構造堆時從最后一個非葉子節點開始調整,其ID最大為堆大小一半,調整過程中只需要比較父節點和左右子節點的大小,將最大的作為父節點,如果左右子節點被交換到父節點時,那么此時我們認為被交換的節點之下可能不滿足堆的特性,需要對其進行調整,這是一個遞歸的操作。當所有非葉子節點被調整完畢,那么此時就完成了堆的初始化。
在每次取出對頂元素之后只需要堆從對頂開始調整堆即可。
int data[];
//調整堆
public void adjustHeap(int[] data,int sizeOfHeap,int index){
int left=2*index+1;
int right=2*index+2;
int largest=index;
if(left<sizeOfHeap&&data[left]>data[index]) largest = left;
if(right<sizeOfHeap&&data[right]>data[largest]) largest=right;
if(largest!=index){
int tmp=data[index];
data[index]=data[largest];
data[largest]=tmp;
adjustHeap(data,sizeOfHeap,largest);
}
}
//初始化堆
public void buildMaxHeap(int[] data){
int size=data.length;
for(int i=size/2;i>=0;i--){
adjustHeap(data,size,i);
}
}
//完全堆排序
public void sortHeap(int[] data){
for(int i=data.length-1;i>=0;i--){
int tmp=data[0];
data[0]=data[i];
data[i]=tmp;
adjustHeap(data,i,0);
}
}
同時根據堆的性質,在一個序列里面取出TopK個數據非常適合堆排序的方式來做到。
public void getTopK(int[] data){
int startN=data.length-1;
int endN=startN-k+1;
if(endN<0) return;
for(int i=startN;i>=endN;i--){
int tmp=data[0];
data[0]=data[i];
data[i]=tmp;
adjustHeap(data,i,0);
}
}
從數組尾部讀取K個即可,當然這里是取得最大的K 個,如果需要最小的K個則可以使用小頂堆。