# 排序算法

[TOC]

### 初级

#### 冒泡排序

``````int out,in;
for(out = size- 1;out > 1;out--){    //outer loop(backward)
for(in = 0;in < out;in++){           //inter loop(forward)
if(a[in] > a[in + 1]){          //out of order?
swap(in,in + 1);             //swap them
}
}
}
``````

#### 选择排序

``````int out,in,min;
for(out = 0;out<nElems - 1;out++){           //outer loop
min = out;                                //minimum
for(in = out + 1;in < nElems;in++){       //inner loop
if(a[in] < a[min]){                  //if min greater
min = in;                        //we have a new min
}
swap(out,min);                       //swap them
}
}
``````

#### 插入排序

``````int in,out;
for(out = 1;out < nElems; out++){    //out is dividing line
long temp = a[out];               //remove marked item
in = out;                         //start shifts at out
while(in > 0 && a[in - 1] >= temp){   //until one is smaller,
a[in] = a[in -1]                //shift item right
--in;
}
a[in] = temp;                   //insert marked item
}
``````

### 中级

#### 归并排序

``````int[] workSpace = new int[source.length];
recMergerSort(source,workSpace,0,length-1);

private static void recMergeSort(int[] source ,int[] workSpace,int lowerBound, int upperBound){

if (lowerBound == upperBound){
return; // if range is 1,no use sorting
} else {
int mid = (lowerBound + upperBound) / 2; //find midpoint
recMergeSort(source,workSpace,lowerBound,mid); // sort low half
recMergeSort(source,workSpace,mid + 1,upperBound); // sort high half
merge(source,workSpace,lowerBound,mid+1 ,upperBound); //merge them
}
}

private static void merge(int[] source,int[] workPlace, int lowPtr, int highPtr, int upperBound) {

int j = 0; // workspace index
int lowerBound = lowPtr;
int mid = highPtr - 1;
int n = upperBound - lowerBound + 1; // size of items
while (lowPtr <= mid && highPtr <= upperBound){
if (source[lowPtr] < source[highPtr]){
workPlace[j++] = source[lowPtr++];
} else {
workPlace[j++] = source[highPtr++]
}
}

while (lowPtr <= mid){
workPlace[j++] = source[lowPtr++];
}

while (highPtr <= upperBound){
workPlace[j++] = source[highPtr++];
}

for (j = 0;j < n; j++) {
source[lowerBound + j] = workPlace[j];
}

}

``````

### 高级

java代码实现：

``````class ArraySh{

private long[] theArray;
private int nElems;

public ArraySh(int max){
theArray = new long[max];
nElems = 0;
}

public void insert(long value){
theArray[nElems] = value;
nElems++;
}

public void shellSort(){
int inner,outer;
long temp;
int h = 1;

while(h <= nElems / 3){
h = h * 3 + 1;
}

while(h > 0){
for(outer=h;outer<nElems;outer++){
temp = theArray[outer];
inner = outer;

while(inner > h - 1 && theArray[inner - h] >= temp){
theArray[inner] = theArray[inner - h];
inner -= h;
}
theArray[inner] = temp;
}
h = (h-1)/3;
}
}

}

``````

#### 划分算法

java代码实现：

``````class ArrayPar{
private long[] theArray;
private int nElems;

public ArrayPar(int max){
theArray = new long[max];
nElems = 0;
}

public void insert(long value){
theArray[nElems] = value;
nElems++;
}

public int partitionIt(int left,int right,long pivot){
int leftPtr = left - 1;
int rightPtr = right + 1;

while(true){
//这里需要检查边界，povit是外界设定，对效率影响很大，在快速排序中有更巧妙的设定方法
while(leftPtr < right && theArray[++leftPtr] < povit);   //find bigger item
while(rightPtr > left && theArray[--rightPtr] > povit);  //find smaller item
if(leftPtr >= rightPtr){      //if pointers cross, partition done
break;
} else {
swap(leftPtr,rightPtr);
}
}
return leftPtr;
}

}

``````

``````while(leftPtr < right && theArray[++leftPtr] < pivot);
``````

``````while(leftPtr < right && theArray[leftPtr] < pivot) {
++leftPtr
};
``````

#### 快速排序

``````class ArrayIns{
private long[] theArray;
private int nElems; // elements number, or size

public ArrayIns(int max){
theArray = new long[max];
nElems = 0;
}

public void insert(long value){
theArray[nElems] = value;
nElems++;
}

public void quickSort(){
recQuickSort(0,nElems - 1);
}

private void recQuickSort(int left,int right){

if(right - left <= 0) {          // if size <= 1, already sorted
return;
} else {
long pivot = theArray[right];     // rightmost item
int partition = partitionIt(left,right,pivot);
recQuickSort(left,partition - 1);    //sort left side
recQuickSort(partition+1,right);     //sort right side
}
} // end recQuickSort()

private int partitionIt(int left,int right,long pivot){
int leftPtr = left - 1;
int rightPtr = right;    //这里设定最右为pivot，所以从right-1开始划分，下面代码会-1

while(true){
while(theArray[++leftPtr] < pivot);
while(rightPtr > 0 && theArray[--rightPtr] > pivot);
if(leftPtr >= rightPtr){
break;
} else {
swap(leftPtr,rightPtr);
}
} // end while(true)

swap(leftPtr,right);    //restore pivot  当0->right-1划分好了之后，交换right和leftPtr的位置，将pivot移动到中间，
return leftPtr;         //return pivot location
}

}

``````

(为什么不扫描要排序的全部数据，取中间值，因为这个做法比排序本身还要费时间，不可行)

``````class ArrayIns{
private long[] theArray;
private int nElems;

private ArrayIns(int max){
theArray = new long[max];
nElems = 0;
}

public void insert(long value){
theArray[nElems] = value;
nElems++;
}

public void quickSort(){
recQuickSort(0,nElems-1);
}

private void recQuickSort(int left,int right){
int size = right - left + 1;
if(size <= 3) {
manualSort(left,right);
} else {
long median = median0f3(left,right);
int partition = partitionIt(left,right,median);
recQuickSort(left,partition - 1);
recQuickSort(partition + 1,right);
}
}

private long medianOf3(int left,int right){
int center = (left + right) / 2;
if(theArray[left] > theArray[center])  swap(left,center);
if(theArray[left] > theArray[right])  swap(left,right);
if(theArray[center] > theArray[right]) swap(center,right);

swap(center,right - 1);   // put pivot on right
return theArray[right -1];
}

private int partitionIt(int left,int right,long pivot){
int leftPtr = left;         //right of first elem
int rightPtr = right -1;    //left of pivot
while(true){
while(theArray[++leftPtr] < pivot);
while(theArray[--rightPtr] > pivot);
if(leftPtr >= rightPtr ){
break;
} else {
swap(leftPtr,rightPtr);
}
}
swap(leftPtr,right-1);
return leftPtr;
}

private void manualSort(int left,int right){
int size = right - left + 1;
if(size <= 1) return;
if(size == 2) {
if(theArray[left] > theArray[right]) swap(left,right);return;
} else {   //size is 3
if(theArray[left] > theArray[right -1]) swap(left,right-1);
if(theArray[left] > theArray[right])  swap(left,right);
if(theArray[right-1]> theArray[right])  swap(right-1,right);

}

}

}

``````

### 推荐阅读更多精彩内容

• 概述：排序有内部排序和外部排序，内部排序是数据记录在内存中进行排序，而外部排序是因排序的数据很大，一次不能容纳全部...
每天刷两次牙阅读 3,166评论 0 16
• Ba la la la ~ 读者朋友们，你们好啊，又到了冷锋时间，话不多说，发车！ 1.冒泡排序（Bub...
王饱饱阅读 1,404评论 0 7
• 概述 排序有内部排序和外部排序，内部排序是数据记录在内存中进行排序，而外部排序是因排序的数据很大，一次不能容纳全部...
蚁前阅读 4,466评论 0 52
• 文／画：拾穗 七夕 何良宵 直叫天下有情人为之疯狂 玫瑰娃娃唯恐天下不乱 满天飞舞 难怪牛郎织女鹊桥难相会 如此美...
拾穗的时光阅读 56评论 2 4
• 在古龙笔下的江湖里，有个温暖的人，叫花满楼。 花满楼是个瞎子，景致再美，不过无边黑夜。 世人看来，目不能视物，本该...
小火乐阅读 102评论 0 1