記錄我的碼農之路~~~
算法爲C++實現。
共包含冒泡排序、選擇排序、插入排序、希爾排序、堆排序、桶排序、快速排序以及歸併排序… …
注:算法是初學自己捋着思路寫的,有不足之處還請大家指正一起優化~~~
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <time.h>
#include <stack>
using namespace std;
class Sort {
public:
/*************************************************************/
template<class T>//冒泡排序
void BubbleSort(T* vec, int n) {
int flag = 0;//標記法判斷是否發生 交換
for (int i = n; i > 1; i--)
{
//一共i個數進行排序
for (int j = 0; j < i - 1; j++)
{
if (vec[j] > vec[j + 1])
{
Swap<T>(vec[j], vec[j + 1]);
flag = 1; //發生交換纔將flag置1
}
}
if (flag == 0) //一整趟下來沒發生交換,說明無需繼續排序,跳出循環
break;
}
}
/*************************************************************/
template<class T>//選擇排序
void SeleteSort(T* vec, int n)
{
for (int i = n; i > 1; i--)//i表示進行選擇排序的數量
{
int indexMax = 0;
for (int j = 1; j < i; j++)
{
if (vec[j] > vec[indexMax])
{
indexMax = j; //尋找最大值下標
}
}
if (indexMax != i - 1)//如果最大值不是當前的“最後”一個元素就交換位置
Swap(vec[indexMax], vec[i - 1]);
}
}
/*************************************************************/
template<class T>//直接插入排序
void InsertSort(T* vec, int n)
{
for (int i = 1; i < n; i++)
{
//有序與無序的分界線
int j = i - 1;
T tmp = vec[i];
for (; j >= 0 && tmp < vec[j]; j--)//找第一個比它小的數
{
//移動過程中完成數據遷移
vec[j + 1] = vec[j];
}
vec[j + 1] = tmp;
}
}
/*************************************************************/
template<class T>//希爾插入排序
void ShellSort(T* vec, int n)
{
for (int gap = n / 2; gap >= 1; gap /= 2)
{
for (int i = 0; i < gap; i++)
groupSort(vec, n / gap, i, gap);
}
}
template<class T>//n代表進行插入排序元素的個數,start爲排序首地址,gap爲間隙
void groupSort(T* vec, int n, int start, int gap)//傳入數組、起始下標、希爾間隙進行插入排序
{
int i, j;
for (i = start + gap; i < n * gap; i += gap)
{
T tmp = vec[i];//用變量tmp記錄需要插入的元素
for (j = i - gap; tmp < vec[j] && j >= 0; j -= gap)
vec[j + gap] = vec[j];
vec[j + gap] = tmp;
}
}
/*************************************************************/
template<class T>//堆排序(堆調整)
void adjustHeap(T* vec, int curindex, int maxindex)
{
int father = curindex;
int child = 2 * father + 1;//左孩子節點
while (child <= maxindex)
{
if (child + 1 <= maxindex && vec[child + 1] > vec[child])//說明有右孩子
child++;//使用右孩子下標(與父節點比較)
if (vec[child] > vec[father])//若孩子節點大於父節點,則交換
{
Swap(vec[child], vec[father]);
father = child; //交換後檢測子節點的位置是否是最大堆
child = 2 * father + 1;
}
else
break;//無交換,跳出循環
}
}
template<typename T>//堆排序
void HeapSort(T* vec, int maxindex)
{
for (int i = (maxindex - 1) / 2; i >= 0; i--)//初始化最大堆結構
adjustHeap(vec, i, maxindex);
for (int i = maxindex; i > 0;)
{
Swap(vec[0], vec[i]);//交換首尾元素
i--;
for (int j = (i - 1) / 2; j >= 0; j--)//調整堆結構爲最大堆
adjustHeap(vec, j, i);//重新對堆進行排序
}
}
/*************************************************************/
template<class T>//桶排序
void BuckerSort(T* vec, int n)
{
T max = vec[0];
for (int i = 1; i < n; i++)
if (vec[i] > max)
max = vec[i];
T* bucket = new T[max + 1]();
for (int i = 0; i < n; i++)
bucket[vec[i]]++;
int start = 0;
for (T i = 0; i < max + 1; i++)
{
while (bucket[i]--) {
vec[start++] = i;
}
}
}
/*************************************************************/
template<typename T>//荷蘭國旗法快速排序
pair<int, int > HL_NtionalFlag(T* vec, int start, int end)
{
int i = start - 1, j = end + 1, index = start;
T flag = vec[index];
while (index < j)
{
if (vec[index] == flag)
index++;
else if (vec[index] < flag) {
Swap(vec[index++], vec[++i]);
}
else {
Swap(vec[index], vec[--j]);
}
}
return make_pair(i, j);
}
template <typename T>
void RecurQuickSort(T* vec, int start, int end)//遞歸法赫拉國旗快排
{
if (start >= end)
return;
pair<int, int> p = HL_NtionalFlag(vec, start, end);
RecurQuickSort(vec, start, p.first);//左半部分
RecurQuickSort(vec, p.second, end);//右半部分
}
template<class T>
void Non_recurQuick(T* vec, int start, int end)//start/end均爲數字下標
{
stack<pair<int, int>> stk;//定義一個pair類型的棧來存儲每次進行荷蘭國旗排序的下標值
stk.push(make_pair(start, end));
while (!stk.empty())
{
pair<int, int> p = stk.top();//得到上一次排序分界線的兩個位置
stk.pop();//用完將棧區變量彈出
pair<int, int> part = HL_NtionalFlag(vec, p.first, p.second);
if (part.first > p.first)//表示這一次左半部分快排有改變
stk.push(make_pair(p.first, part.first));//上次排序的i值是開始,排序完的i是結束的位置
if (part.second < p.second)
stk.push(make_pair(part.second, p.second));//上次的j是結束的位置,排序完是開始id位置
}
}
/*************************************************************/
template<class T>//歸併整合
void Merge(T* vec, int l,int mid, int r)
{
T* help = new T[r - l + 1];//堆區申請空間
int index = 0,i = l,j = mid + 1;
while (i <= mid && j <= r)//兩部分數組分別比較
{
if (vec[i] <= vec[j])
help[index++] = vec[i++];
else
help[index++] = vec[j++];
}
while (i <= mid)//將兩部分中還沒放入help數組中元素逐一放進去
{
help[index++] = vec[i++];
}
while (j <= r)
{
help[index++] = vec[j++];
}
//將元素從help數組重新放入原地
index = l;//記錄原數組最小下標
for (i = 0; i < r - l + 1; i++)
vec[index++] = help[i];
delete[] help;
}
template<typename T>//歸併排序
void MergeSort(T* vec, int l,int r)
{
int mid = (l + r) / 2;
if (l >= r)//將數組不斷分裂,到單塊數組長度爲 1 時停止,跳出遞歸
{
return;
}
MergeSort(vec, l, mid); //遞歸調用
MergeSort(vec, mid + 1, r);
//分裂後進行逐層排序組合
Merge(vec, l, mid, r);
}
/*************************************************************/
template<class T>//打亂數組
void Interupt(T* p, int n)//隨機打亂數組
{
srand(time(0));
for (int i = 0; i < 100000; i++)//產生模擬時間差
for (int j = 0; j < 5000; j++);
for (int i = 0; i < n; i++)
{
int j = rand() % n;
Swap<T>(p[i], p[j]);
}
}
/*************************************************************/
template<class T>//打印數組
void PrintVec(T* vec, int n)
{
for (int i = 0; i < n; i++)
cout << vec[i] << " ";
cout << endl;
}
/************************************************************/
template<class T>//交換元素
void Swap(T& a, T& b)
{
T t = a;
a = b;
b = t;
}
};
int main() {
Sort s;
int a[] = {
2,1,3,5,4,6,8,7};
int n = sizeof(a)/sizeof(int);
cout << "原數組:" << endl;
s.PrintVec(a, n);
cout << endl << "堆排序:" << endl;;
s.HeapSort(a, n - 1);
s.PrintVec(a, n);
cout << endl << "打亂後數組:" << endl;;
s.Interupt(a, n);
s.PrintVec(a, n);
cout << endl << "桶排序:" << endl;;
s.BuckerSort(a, n);
s.PrintVec(a, n);
cout << endl << "打亂後數組:" << endl;;
s.Interupt(a, n);
s.PrintVec(a, n);
cout << endl << "冒泡排序:" << endl;;
s.BubbleSort(a, n);
s.PrintVec(a, n);
cout << endl << "打亂後數組:" << endl;;
s.Interupt(a, n);
s.PrintVec(a, n);
cout << endl << "插入排序:" << endl;;
s.InsertSort(a, n);
s.PrintVec(a, n);
cout << endl << "打亂後數組:" << endl;;
s.Interupt(a, n);
s.PrintVec(a, n);
cout << endl << "選擇排序:" << endl;;
s.SeleteSort(a, n);
s.PrintVec(a, n);
cout << endl << "打亂後數組:" << endl;;
s.Interupt(a, n);
s.PrintVec(a, n);
cout << endl << "希爾排序:" << endl;;
s.ShellSort(a, n);
s.PrintVec(a, n);
cout << endl << "打亂後數組:" << endl;
s.Interupt(a, n);
s.PrintVec(a, n);
cout << endl << "快速排序(遞歸):" << endl;
s.RecurQuickSort(a, 0, n - 1);
s.PrintVec(a, n);
cout << endl << "打亂後數組:" << endl;
s.Interupt(a, n);
s.PrintVec(a, n);
cout << endl << "快速排序(非遞歸):" << endl;
s.Non_recurQuick(a, 0, n - 1);
s.PrintVec(a, n);
cout << endl << "打亂後數組:" << endl;
s.Interupt(a, n);
s.PrintVec(a, n);
cout << endl << "歸併排序:" << endl;
s.MergeSort(a, 0, n - 1);
s.PrintVec(a, n);
return 0;
}
效果圖: