1.八大排序算法比較
2.八大算法實現
#include <iostream>
using namespace std;
//冒泡排序:從前向後比,每次選出最大的放後面
void Bubble_Sort1(int a[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j<n - 1 - i; j++)
{
if (a[j]>a[j + 1]) // 這裏是從小到大排序,如果是從大到小排序,只需將“>”換成“<”
{
int temp;
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
}
//冒泡排序:從後向前比,每次選出最小的放前面
void Bubble_Sort2(int a[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = n - 1; j > i; j--)
{
if (a[j - 1]>a[j])
{
int temp;
temp = a[j];
a[j] = a[j - 1];
a[j - 1] = temp;
}
}
}
}
//快速排序
void Quick_Sort(int a[], int left, int right)
{
if (left< right)
{
int i = left, j = right, temp = a[left];
while (i < j)
{
while (i < j && a[j] >= temp) // 從右向左找第一個小於x的數
j--;
if (i < j) {
a[i] = a[j];
i++;
}
while (i < j && a[i]< temp) // 從左向右找第一個大於等於x的數
i++;
if (i < j) {
a[j] = a[i];
j--;
}
}
a[i] = temp;
Quick_Sort(a, left, i - 1); // 遞歸調用
Quick_Sort(a, i + 1, right);
}
}
//直接選擇排序
void Select_Sort(int a[], int n)
{
int i, j, min;
for (i = 0; i < n-1; i++)//i爲已排序序列的末尾
{
min = i; //記錄最小值的位置
for (j = i + 1; j < n; j++) {
if (a[j] < a[min]) //找出未排序序列中的最小值
min = j;
}
if (min != i)
swap(a[i], a[min]); //swap()是在std::標準名詞空間中的
}
}
//堆排序:大根堆向下調整
//性質一:索引爲i的左孩子的索引是(2 * i + 1);
//性質二:索引爲i的左孩子的索引是(2 * i + 2);
//性質三:索引爲i的父結點的索引是 floor((i - 1) / 2);
//參數start -- 被下調節點的起始位置(一般爲0,表示從第1個開始)
//參數end -- 截至範圍(一般爲數組中最後一個元素的索引)
void maxHeapDown(int a[], int start, int end)
{
int current = start; // 當前(current)節點的位置
int left = 2 * current + 1; // 爲左(left)孩子的位置
int tmp = a[current]; // 當前(current)節點的值
for (; left <= end; current = left, left = 2 * left + 1)
{
// "left"是左孩子,"left+1"是右孩子
if (left < end && a[left] < a[left + 1])
left++; // 左右兩孩子中選擇較大者
if (tmp >= a[left])
break; // 調整結束
else // 交換值
{
a[current] = a[left];
a[left] = tmp;
}
}
}
//堆排序(升序):交換數據,將a[1]和a[n]交換,使a[n]是a[1...n]中的最大值;然後將a[1...n-1]重新調整爲最大堆。
void Heap_Sort_Asc(int a[], int n)
{
int i, tmp;
for (i = n / 2 - 1; i >= 0; i--) // 從(n/2-1) --> 0逐次遍歷。遍歷之後,得到的數組實際上是一個(最大)二叉堆。
maxHeapDown(a, i, n - 1);
//交換數據
for (i = n - 1; i > 0; i--)
{
// 交換a[0]和a[i]。交換後,a[i]是a[0...i]中最大的。
tmp = a[0];
a[0] = a[i];
a[i] = tmp;
// 調整a[0...i-1],使得a[0...i-1]仍然是一個最大堆。
maxHeapDown(a, 0, i - 1);
}
}
//堆排序:小根堆向下調整
void minHeapDown(int a[], int start, int end)
{
int current = start; // 當前(current)節點的位置
int left = 2 * current + 1; // 爲左(left)孩子的位置
int tmp = a[current]; // 當前(current)節點的值
for (; left <= end; current = left, left = 2 * left + 1)
{
// "left"是左孩子,"left+1"是右孩子
if (left < end && a[left] > a[left + 1])
left++; // 左右兩孩子中選擇較小者
if (tmp <= a[left])
break; // 調整結束
else // 交換值
{
a[current] = a[left];
a[left] = tmp;
}
}
}
//堆排序(降序):交換數據,將a[1]和a[n]交換,使a[n]是a[1...n]中的最小值;然後將a[1...n-1]重新調整爲最小堆。
void Heap_Sort_Desc(int a[], int n)
{
int i, tmp;
for (i = n / 2 - 1; i >= 0; i--) // 從(n/2-1) --> 0逐次遍歷。遍歷之後,得到的數組實際上是一個(最小)二叉堆。
minHeapDown(a, i, n - 1);
//交換數據
for (i = n - 1; i > 0; i--)
{
// 交換a[0]和a[i]。交換後,a[i]是a[0...i]中最小的。
tmp = a[0];
a[0] = a[i];
a[i] = tmp;
// 調整a[0...i-1],使得a[0...i-1]仍然是一個最小堆。
minHeapDown(a, 0, i - 1);
}
}
//希爾排序
void Shell_Sort(int a[], int n)
{
int i, j, gap;
// gap爲步長,每次減爲原來的一半。
for (gap = n / 2; gap > 0; gap /= 2)
{
// 共gap個組,對每一組都執行直接插入排序
for (i = 0; i < gap; i++)
{
for (j = i + gap; j < n; j += gap)
{
// 如果a[j] < a[j-gap],則尋找a[j]位置,並將後面數據的位置都後移。
if (a[j] < a[j - gap])
{
int tmp = a[j];
int k = j - gap;
while (k >= 0 && a[k] > tmp)
{
a[k + gap] = a[k];
k -= gap;
}
a[k + gap] = tmp;
}
}
}
}
}
//直接插入排序
void Insert_Sort(int a[], int n)
{
int i, j, k;
for (i = 1; i < n; i++)
{
for (j = i - 1; j >= 0; j--) //爲a[i]在前面的a[0...i-1]有序區間中找一個合適的位置
if (a[j] < a[i])
break;
if (j != i - 1) //如找到了一個合適的位置
{
int temp = a[i];
for (k = i - 1; k > j; k--) //將比a[i]大的數據向後移
a[k + 1] = a[k];
a[k + 1] = temp; //將a[i]放到正確位置上
}
}
}
//歸併排序:將兩個相鄰有序區間合併成一個
void merge(int* a, int start, int mid, int end)
{
int *tmp = new int[end - start + 1]; // tmp是彙總2個有序區的臨時區域
int i = start; // 第1個有序區的索引
int j = mid + 1; // 第2個有序區的索引
int k = 0; // 臨時區域的索引
while (i <= mid && j <= end)
{
if (a[i] <= a[j])
tmp[k++] = a[i++];
else
tmp[k++] = a[j++];
}
while (i <= mid)
tmp[k++] = a[i++];
while (j <= end)
tmp[k++] = a[j++];
// 將排序後的元素,全部都整合到數組a中。
for (i = 0; i < k; i++)
a[start + i] = tmp[i];
delete[] tmp;
}
//歸併排序:從上到下(遞歸方式)
void Merge_Sort(int* a, int start, int end)
{
if (a == NULL || start >= end)
return;
int mid = (end + start) / 2;
Merge_Sort(a, start, mid); // 遞歸排序a[start...mid]
Merge_Sort(a, mid + 1, end); // 遞歸排序a[mid+1...end]
// a[start...mid] 和 a[mid...end]是兩個有序空間,
// 將它們排序成一個有序空間a[start...end]
merge(a, start, mid, end);
}
//基數排序:計算數組裏最大位數,即爲進行排序次數
int maxbit(int a[], int n)
{
int d = 1; //保存最大的位數
int p = 10;
for (int i = 0; i < n; i++)
{
while (a[i] >= p)
{
p *= 10;
d++;
}
}
return d;
}
//基數排序
void Radix_Sort(int a[], int n)
{
int d = maxbit(a,n);
int *tmp = new int[n]; //int tmp[n]錯誤定義,數組長度必須是整數常量或整數符號常量,想要用變量設置大小,必須用動態分配
int count[10]; //計數器
int i, j, k;
int radix = 1;
for (i = 1; i <= d; i++) //進行d次排序
{
for (j = 0; j < 10; j++)
count[j] = 0; //每次分配前清空計數器
for (j = 0; j < n; j++)
{
k = (a[j] / radix) % 10; //統計每個桶中的記錄數
count[k]++;
}
for (j = 1; j < 10; j++)
count[j] = count[j - 1] + count[j]; //這時count裏的值表示在tmp中的位置(減一爲tmp裏的存儲下標)
for (j = n - 1; j >= 0; j--) //將所有桶中記錄依次收集到tmp中
{
k = (a[j] / radix) % 10;
tmp[count[k] - 1] = a[j];
count[k]--; //用於一個桶中有多個數,減一爲桶中前一個數在tmp裏的位置
}
for (j = 0; j < n; j++) //將臨時數組的內容複製到data中
a[j] = tmp[j];
radix = radix * 10;
}
delete[] tmp;
}
int main()
{
int arr[] = { 61, 17, 29, 22, 34, 60, 72, 21, 50, 1, 62 };
int len = sizeof(arr) / sizeof(*arr); //int len = (int) sizeof(arr) / sizeof(arr[0]);
//Bubble_Sort1(arr, len);
//Bubble_Sort2(arr, len);
//Quick_Sort(arr, 0, len - 1);
//Select_Sort(arr, len);
//Heap_Sort_Asc(arr, len);
//Heap_Sort_Desc(arr,len);
//Shell_Sort(arr, len);
//Insert_Sort(arr, len);
//Merge_Sort(arr, 0, len - 1);
Radix_Sort(arr, len);
cout << "排序後的數組元素:" << endl;
for (int i = 0; i < len; i++)
{
cout << arr[i] << " ";
}
cout << endl;
return 0;
}