第一篇博客實現了三種最基本最簡單的排序算法,本篇文章將在這三種算法的基礎上稍微演變一下。
1.快排
光從名字看就知道速度肯定不差,前一篇講的冒泡排序,怎麼看都不算是一種好的排序算法,裏面充斥了太多的無謂的交換動作,時間複雜度倒是很穩定o(n^2),但對於排序算法實在說不過去。快排是冒泡排序的改進版,思路就是分治,將一個序列隨機按照某個值分成兩個子序列,子序列A裏面的值全部比該值大,另一個子序列B的值全部比該值小,這聽起來像是二叉排序樹。然後依次對子序列進行如上操作,很明顯快排最簡單的實現就是用遞歸。
看下java實現的快排:
/**
* 快速排序,最快O(nlogn) 最差O(n^2)
*
* @param low
* @param high
* @param array
*/
public static void quickSort(int low, int high, int[] array) {
if (low >= high) {
return;
}
int i = low;
int j = high;
// 此處選取的中軸爲當前i和j的中間值
int m = (i + j) / 2;
int temp = array[m];
array[m] = array[high];
array[high] = temp;
// 中軸
int pivotkey = array[high];
while (i < j) {
while (i < j && array[i] <= pivotkey) {
i++;
}
array[j] = array[i];
while (i < j && array[j] >= pivotkey) {
j--;
}
array[i] = array[j];
}
// 此時i和j相等,替換當前i的值
array[i] = pivotkey;
//對左子集做快排
quickSort(low, i - 1, array);
//對右子集做快排
quickSort(i + 1, high, array);
}
再來看下python的實現:
def quickSort(low,high,array):
if low > high:
return
i ,j = low,high
m = (i+j)/2
temp = array[m]
array[m] = array[high]
array[high] = temp
pivotkey = array[high]
while i < j:
while i < j and array[i] < pivotkey:
i+=1
array[j] = array[i]
while i < j and array[j] >= pivotkey:
j-=1
array[i] = array[j]
array[i] = pivotkey
quickSort(low,i-1,array)
quickSort(i+1,high,array)
/**
* 二分查找index的插入排序
* @param array
*/
public static void insertSortBinary(int[] array)
{
for(int i=1;i<array.length;i++)
{
int temp = array[i];
int index = binarySearch(0, i, array, array[i]);
for(int j=i;j>index;j--)
{
array[j] = array[j-1];
}
array[index] = temp;
}
}
/**
* 二分查找微改版
* @param start
* @param end
* @param array
*/
public static int binarySearch(int start,int end,int[] array,int value)
{
while(start <= end)
{
int mid = (start + end)/2;
if(array[mid] == value)
{
return mid;
}
else if(array[mid] < value)
{
start = mid + 1;
}
else
{
end = mid - 1;
}
}
return start;
}
def insertSortBinary(array):
for i in xrange(1,len(array)):
index = binarySerach(array,array[i])
for j in range(index,i)[::-1]:
array[j] = array[j-1]
array[i],array[index] = array[index],array[i]
def binarySerach(array,value):
low,high = 0,len(array)-1
while low <= high:
mid = (low + high)/2
if value == array[mid]:
return mid
elif value < array[mid] :
high = mid -1
else :
low = mid + 1
return low
希爾排序也是一種插入排序,只不過它先讓整體的序列保持部分有序,這樣可以加快排序速度,java實現:/**
* 希爾排序,步長g 直接插入排序如果部分有序則速度明顯提升,因此考慮 使用分治法,先讓子集有序,然後在插入這裏有個步長的概念,
* 即這個步長內的子集有序,逐步擴大步長,從而做到整體有序
*/
public static void shellSort(int[] array) {
int[] gs = {5,4,3,2,1};
for(int i=0;i<gs.length;i++)
{
shellInsert(array, gs[i]);
}
}
/**
* 希爾插入,只不過多了步長g
*
* @param array
* @param g
*/
public static void shellInsert(int[] array, int g) {
int temp,j;
for (int i = g; i < array.length; i += g) {
temp = array[i];
for (j = i - g; j >= 0; j-=g) {
if (temp < array[j]) {
array[j + g] = array[j];
} else {
break;
}
}
array[j+g] = temp;
}
}
python實現:def shellInsert(array,g):
for i in range(g,len(array),g):
if array[i] < array[i-g]:
temp = array[i]
for j in range(0,i,g)[::-1]:
if temp < array[j]:
array[j+g] = array[j]
else:
j+=g
break
array[j] = temp
def shellSort(array):
gap = [5,4,3,2,1]
for x in range(1,6)[::-1]:
shellInsert(array,x)
/**
* 調整某個子堆,從i節點開始從上到下調整。 將最大值調整到堆頂
*
* @param array
* @param i
*/
public static void adjustHeap(int[] array, int i, int len) {
int maxIndex = i;
// i爲葉子及節點
if ((2 * i + 1) >= len) {
return;
}
// 肯定有左孩子
else {
// 左孩子大於父親
if (array[i] < array[2 * i + 1]) {
maxIndex = 2 * i + 1;
// 有右孩子
}
if ((2 * i + 2) < len) {
System.out.println("have right");
if (array[maxIndex] < array[2 * i + 2]) {
maxIndex = 2 * i + 2;
}
}
}
// 交換
if (maxIndex != i) {
int temp = array[i];
array[i] = array[maxIndex];
array[maxIndex] = temp;
// 遞歸調整
adjustHeap(array, maxIndex, len);
}
}
/**
* 堆的建立過程,是從底像上不斷調整的過程,最先開始調整的是最後一個非葉子節點
*
* @param array
*/
public static void createHeap(int[] array) {
if (array.length <= 1) {
return;
}
// 從最後一個非葉子節點開始調整
for (int i = array.length / 2 - 1; i >= 0; i--) {
adjustHeap(array, i, array.length);
}
}
public static void heapSort(int array[]) {
createHeap(array);
for (int i = array.length - 1; i >= 0; i--) {
int temp = array[0];
array[0] = array[i];
array[i] = temp;
adjustHeap(array, 0, i);
}
}
def heapSort(array):
buildHeap(array)
for x in xrange(0,len(array)):
array[0],array[len(array)-x-1] = array[len(array)-x-1],array[0]
adjustHeap(array,len(array)-x-1,0)
#from last no leave node
def buildHeap(array):
x = len(array)/2 - 1
while x>=0:
adjustHeap(array,len(array)-x,x)
x-=1
#from top to down
def adjustHeap(array,size,root):
maxIndex = root
if (2*root + 1) >= size:
return
if array[2*root+1] > array[maxIndex]:
maxIndex = 2*root + 1
if (2*root+2) < size:
if array[2*root+2] > array[maxIndex]:
maxIndex = 2*root+2
if maxIndex!=root:
array[maxIndex],array[root] = array[root],array[maxIndex]
adjustHeap(array,size,maxIndex)
/**
* 歸併排序,遞歸調用
* @param array
* @param start
* @param end
*/
public static void mergeSort(int[] array,int start,int end)
{
if(start >= end)
{
return;
}
int mid = (start + end)/2;
mergeSort(array, start, mid);
mergeSort(array,mid + 1,end);
merge(array,start,end,mid);
}
/**
* merge方法,合併兩個有序的子集
* @param array
* @param start
* @param end
*/
public static void merge(int[] array,int start,int end,int mid)
{
int[] temp = new int[end - start + 1];
int i = start;
int j = mid +1;
int k = 0;
while (i <= mid && j<=end)
{
if(array[i] < array[j])
{
temp[k++] = array[i++];
}
else
{
temp[k++] = array[j++];
}
}
//拷貝剩餘的值到temp
while (i<=mid)
{
temp[k++] = array[i++];
}
while (j<=end)
{
temp[k++] = array[j++];
}
System.arraycopy(temp,0,array,start,end - start +1);
}
python實現:def mergeSort(array,low,high):
if low>=high:
return
mid = (low+high)/2
mergeSort(array,low,mid)
mergeSort(array,mid+1,high)
merge(array,low,high,mid)
#merge two list
def merge(array,low,high,mid):
temp_array = []
i,j = low,mid+1
while i<=mid and j<=high:
if array[i]<array[j]:
temp_array.append(array[i])
i+=1
else:
temp_array.append(array[j])
j+=1
while i<=mid:
temp_array.append(array[i])
i+=1
while j<=high:
temp_array.append(array[j])
j+=1
for x in xrange(0,len(temp_array)):
array[low] = temp_array[x]
low+=1
最近這段時間在出差,基本沒有時間寫博客了,不過還是擠出一點兒時間完成它,不然有些東西沒完成,心裏總是不舒服。