經典排序演算法-快速排序(挖坑法、前後指標法)、基數排序
阿新 • • 發佈:2019-01-05
快速排序在實際應用中是比較表現好的排序演算法。快速排序我用兩種方法實現它。
第一種為方法,形象的稱為:挖坑法
基本思路:1、尋找pos位,然後將其分為兩段陣列,然後對這兩段陣列遞迴排序;
2、指定一個基數temp(三數取中法),定義兩個指標begin一個指向起始位置,end一個指向最後一個元素的位置。begin尋找比基數(temp)大的數字,找到 後將begin的資料賦給end,begin成為一個坑,然後end尋找比基數(temp)小的數字,找到將end的資料賦給begin,end成為一個新坑,迴圈這個過程,直到begin指標與end指標相遇,然後將temp的資料返回給那個坑,然後進行遞迴操作。
程式碼實現為:
前後指標法:int PastSort1(int *arr, int left, int right) //挖坑法 { int begin = left; int end = right; int temp = arr[mid(arr,left,right)]; while (begin < end) { while (begin < end && arr[begin] <= temp) begin++; if (begin < end) arr[end] = arr[begin];//begin成為新坑 while (begin < end && arr[end] >= temp) end--; if (begin < end) arr[begin] = arr[end]; //end成為新坑 } arr[begin] = temp; //將temp填補進去 return begin; } void QuickSort(int *arr,int left,int right) { if (arr == NULL || left > right) return; int pos = PastSort1(arr, left, right); QuickSort(arr, left, pos - 1); QuickSort(arr, pos + 1, right); }
定義兩個指標,一前一後,前面指標找比基數小的數,後面指標找比基數大的數,前面的指標找到後,將前後指標所指向的資料交換,當前面的指標遍歷完整個陣列時,將基數值與後指標的後一個位置的資料進行交換,然後以後指標的後一個位置作為分界,然後將陣列分開,進行遞迴排序。
程式碼實現:
基數排序:int PastSort2(int* arr, int left, int right) //前後指標法 { int cur = left; //找小 int ptr = left-1;//找大 int temp = arr[mid(arr, left, right)]; while (cur < right) { if (arr[cur] < temp) { swap(arr[cur], arr[++ptr]); } cur++; } swap(arr[++ptr], arr[right]); return ptr; } void QuickSort(int *arr,int left,int right) { if (arr == NULL || left > right) return; int pos = PastSort2(arr, left, right); QuickSort(arr, left, pos - 1); QuickSort(arr, pos + 1, right); }
基本原理是:
程式碼實現為:
int getbit(int* arr,int size) //獲得最大位數
{
int bits = 1;
int rang = 10;
for (int i = 0; i < size; ++i)
{
while (arr[i] >= rang)
{
++bits;
rang *= 10;
}
}
return bits;
}
void BucketSort(int* arr, int size)
{
int bits = getbit(arr, size);
int radix = 1;
int count[10];
for (int bit = 1; bit <= bits;bit++) //迴圈最大位數次
{
memset(count, 0, sizeof(int)* 10);
for (int i = 0; i < size; ++i)//統計數字位數的數量
{
int index = (arr[i] / radix) % 10;
count[index]++;
}
for (int j = 1; j < 10; j++) //固定數值排序的位置
{
count[j] = count[j] + count[j - 1];
}
int *str = new int[size];
memset(str, 0, sizeof(int)*size);
for (int i = size-1; i >=0; i--)//按照固定的位置將資料寫入輔助陣列
{
int index = (arr[i] / radix) % 10;
str[count[index]-1] = arr[i];
count[index]--;
}
radix = radix * 10;
for (int i = 0; i < size; i++) //將輔助陣列中的數拷貝回原陣列
{
arr[i] = str[i];
}
delete[] str;
}
}
前面我用了三篇文章來寫幾種常見的排序方法,我用一個圖簡單分析一下他們的最好最壞平均時間複雜度,以及空間複雜度,與穩定性分析。