记录我的码农之路~~~
算法为C++实现。
共包含 冒泡排序、 选择排序、 插入排序、 希尔排序、 堆排序、 桶排序、 快速排序以及 归并排序… …
注:算法是初学自己捋着思路写的,有不足之处还请大家指正一起优化~~~
时间、空间复杂度一览:
排序 | 平均时间复杂度 | 最优情况 | 最坏情况 | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O(N^2) | O(N) | O(N^2) | O(1) | 稳定 |
选择排序 | O(N^2) | O(N^2) | O(N^2) | O(1) | 不稳定 |
插入排序 | O(N^2) | O(N) | O(N^2) | O(1) | 稳定 |
希尔排序 | O(N^1.3) | O(^1.3) | O(N^2) | O(1) | 不稳定 |
堆排序 | O(N*logN) | O(N*logN) | O(N*logN) | O(1) | 不稳定 |
归并排序 | O(N*logN) | O(N*logN) | O(N*logN) | O(N) | 稳定 |
快速排序 | O(N*logN) | O(N*logN) | O(N*logN) | O(logN) | 不稳定 |
桶排序 | O(N) | O(N) | O(N) | O(N+M) | 不稳定 |
注:桶排序中M指所用桶的数量。
排序
冒泡排序
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;
}
}
时间复杂度O(N^2) 空间复杂度O(1)
选择排序
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]);
}
}
时间复杂度O(N^2) 空间复杂度O(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;
}
}
时间复杂度O(N^2) 空间复杂度O(1)
希尔排序
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; 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;
}
}
时间复杂度O(N^1.3) 空间复杂度O(1)
堆排序
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);//重新对堆进行排序
}
}
时间复杂度O(N*logN) 空间复杂度O(1)
桶排序
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;
}
}
}
时间复杂度O(N) 空间复杂度O(N)
快速排序
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位置
}
}
时间复杂度O(N*logN) 空间复杂度O(logN)
归并排序
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);
}
时间复杂度O(N*logN) 空间复杂度O(N)
完整代码
#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 ; 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;
}
效果图:
未完待续~~~