#include "stdafx.h"
#include "Sort.h"
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
//打印
void PrintArray(vector<int>& dataArray)
{
const int datasize = dataArray.size();
for (int i = 0; i < (int)dataArray.size(); i++)
cout<<dataArray[i]<<" ";
cout<<endl;
}
//冒泡排序O(n^2),稳定
//两两比较交换,倒序从大到小不断冒出
void BubbleSort(vector<int>& dataArray)
{
const int datasize = dataArray.size();
if (datasize <= 0)
return;
for (int i = 0; i < datasize-1; i++)
{
for (int j = 0; j < datasize-1-i; j++)
{
if (dataArray[j] > dataArray[j+1])
swap(dataArray[j], dataArray[j+1]);
}
}
}
//插入排序O(n^2),稳定
//将待排元素插入到已排序好的序列中
void InsertSort(vector<int>& dataArray)
{
const int datasize = dataArray.size();
if (datasize <= 0)
return;
for (int i = 1; i < datasize; i++)
{
int temp = dataArray[i];
int j;
for (j = i; j-1 >= 0 && temp < dataArray[j-1]; j--)//往后移动,直到找到第一个比待排元素小的位置
{
dataArray[j] = dataArray[j-1];
}
dataArray[j] = temp;
}
}
//希尔排序约为O(n^1.3),最坏的时间复杂度是O(n^2),基于增量的插入排序,不稳定
void ShellSort(vector<int>& dataArray)
{
const int datasize = dataArray.size();
if (datasize <= 0)
return;
for (int div = datasize/2; div >= 1; div /= 2)
{
for (int i = div; i < datasize; i += div) //插入排序,增量为div,而不是1
{
int temp = dataArray[i];
int j;
for (j = i; j-div >= 0 && temp < dataArray[j-div]; j -= div)
{
dataArray[j] = dataArray[j-div];
}
dataArray[j] = temp;
}
}
}
//选择排序O(n^2),不稳定
//从小到大逐个找出
void SelectSort(vector<int>& dataArray)
{
const int datasize = dataArray.size();
if (datasize <= 0)
return;
for (int i = 0; i < datasize; i++)
{
int minPos = i;
for (int j = i+1; j < datasize; j++)
{
if (dataArray[minPos] > dataArray[j])
minPos = j;
}
if (minPos != i)
swap(dataArray[i], dataArray[minPos]);
}
}
//归并排序O(n*logn),稳定
void Merge(vector<int>& dataArray, vector<int>& tempArray, int start, int mid, int end)
{
int i = start;
int j = mid+1;
int k = start;
while (i <= mid && j <= end)
{
if (dataArray[i] > dataArray[j])
tempArray[k++] = dataArray[j++];
else
tempArray[k++] = dataArray[i++];
}
while (i <= mid)
tempArray[k++] = dataArray[i++];
while (j <= end)
tempArray[k++] = dataArray[j++];
for (k = start; k <= end; k++)
dataArray[k] = tempArray[k];
}
void MergeSort(vector<int>& dataArray, vector<int>& tempArray, int start, int end)
{
if (dataArray.empty())
return;
if (start < end)
{
int mid = (start+end)/2;
MergeSort(dataArray, tempArray, start, mid);
MergeSort(dataArray, tempArray, mid+1, end);
Merge(dataArray, tempArray, start, mid, end);
}
}
//向下调整函数
//pos如果从0开始,左结点为2*n+1, 右结点为2*n+2
//pos如果从1开始,左结点为2*n, 右结点为2*n+1
void SiftDown(int *pArray, int nArrayCount, int pos)
{
//从父结点开始,父结点必须比子结点都大
int maxpos = pos;
while (pos*2+1 < nArrayCount)//有子结点
{
//从父结点和两个子结点中,选取一个最大的
if (pArray[pos] < pArray[pos*2+1])
maxpos = pos*2+1;
else
maxpos = pos;
if (pos*2+2 < nArrayCount && pArray[maxpos] < pArray[pos*2+2])
maxpos = pos*2+2;
if (maxpos != pos)
{//父结点比子结点小,则交换,并且继续往下调整
swap(pArray[pos], pArray[maxpos]);
pos = maxpos;
}
else
{//退出,父结点比子结点大
break;
}
}
}
//堆排序O(nlogn),不稳定,基于完全二叉树(叶结点只能出现在最下层或次下层,并且不允许只有右结点没有左结点),选择排序的一种
void HeapSort(vector<int>& dataArray)
{
const int datasize = dataArray.size();
if (datasize <= 0)
return;
//建大根堆
for (int i = datasize/2; i >= 0; i--) //从最后一个非叶结点开始
{
SiftDown(&dataArray[0], datasize, i);
}
//排序,依次把大的挪到最后,然后调整堆
for (int i = dataArray.size()-1; i > 0; i--)
{
swap(dataArray[i], dataArray[0]);
SiftDown(&dataArray[0], i, 0);
}
}
void HeapSort_STL(vector<int>& dataArray)
{
if (dataArray.empty())
return;
make_heap(dataArray.begin(), dataArray.end()/*, greater<int>()*/); //建堆
sort_heap(dataArray.begin(), dataArray.end()/*, greater<int>()*/); //排序
}
//快速排序O(nlogn),分治递推, 不稳定
void QSort(vector<int>& dataArray, int left, int right)
{
if (dataArray.empty())
return;
if (left >= right)
return;
int key = dataArray[left]; //取第一位为基准线
int i = left;
int j = right;
while (i != j)
{
//哨兵,从右往左数,找第一个比key小的数,不断逼近
while (dataArray[j] >= key && i < j)
j--;
//哨兵,从左往右数,找第一个比key大的数,不断逼近
while (dataArray[i] <= key && i < j)
i++;
//交换位置
if (i < j)
swap(dataArray[i], dataArray[j]);
}
//基准数归位
swap(dataArray[i], dataArray[left]);
//分治
QSort(dataArray, left, i-1);
QSort(dataArray, i+1, right);
}
//快排优化(三数取中+插入排序+聚集相等),解决升序、降序、重复三种极坏情况
void QSort_Optimize(vector<int>& dataArray, int left, int right)
{
if (dataArray.empty())
return;
if (right - left + 1 < 10)
{
InsertSort(dataArray);
return;
}
if (left >= right)
return;
//三数取中
int mid = (left+right)/2;
if (dataArray[mid] > dataArray[right])
swap(dataArray[right], dataArray[mid]);
if (dataArray[left] > dataArray[right])
swap(dataArray[left], dataArray[right]);
if (dataArray[mid] > dataArray[left])
swap(dataArray[left], dataArray[mid]);
int key = dataArray[left]; //取第一位为基准线
int i = left;
int j = right;
int leftlen = 0;
int rightlen = 0;
while (i != j)
{
//哨兵,从右往左数,找第一个比base小的数,不断逼近
while (dataArray[j] >= key && i < j)
{
if (dataArray[j] == key)//把相同的往后放
{
swap(dataArray[j],dataArray[right-rightlen]);
rightlen++;
}
j--;
}
//哨兵,从左往右数,找第一个比base大的数,不断逼近
while (dataArray[i] <= key && i < j)
{
if (dataArray[i] == key)//把相同的往前放
{
swap(dataArray[i],dataArray[left+leftlen]);
leftlen++;
}
i++;
}
//交换位置
if (i < j)
swap(dataArray[i], dataArray[j]);
}
//基准数归位,下面的过程包含了这个步骤,所以不需要再进行
//swap(dataArray[i], dataArray[left]);
//把相同的数挪到基准数的两边
int low = left;
int high = i;
while (low <= high && dataArray[low] == key)
{
swap(dataArray[low], dataArray[high]);
low++;
high--;
}
low = i+1;
high = right;
while (low <= high && dataArray[high] == key)
{
swap(dataArray[low], dataArray[high]);
low++;
high--;
}
//分治
QSort_Optimize(dataArray, left, i-leftlen);
QSort_Optimize(dataArray, i+1+rightlen, right);
}
//基数排序O(n),稳定
void RadixSort(vector<int>& dataArray)
{
const int datasize = dataArray.size();
if (datasize <= 0)
return;
//求最大位数
int maxbit = 1;
int p = 10;
for (int i = 0; i < datasize; i++)
{
while (dataArray[i] >= p)
{
p *= 10;
maxbit++;
}
}
//从低到高按位排序,从个位开始
int countArray[10]; //10进制10个桶
vector<int> tempArray(dataArray.size(), 0);
for (int i = 0, radix =1; i <= maxbit; i++, radix *= 10) //按位
{
//统计每个桶中的记录数
memset(countArray, 0 , sizeof(countArray));
for (int j = 0; j < datasize; j++)
countArray[dataArray[j]/radix%10]++;
//将记录数转换为位置
for (int j = 1; j < 10; j++)
countArray[j] = countArray[j-1]+countArray[j];
//按位排序缓存到tempArray
for (int j = datasize-1, index = 0; j >= 0; j--)//倒序
{
index = dataArray[j]/radix%10;
tempArray[countArray[index]-1] = dataArray[j];
countArray[index]--;
}
//复制
for (int j = 0; j < datasize; j++)
dataArray[j] = tempArray[j];
}
}
//计数排序O(N+M),稳定,最简单的桶排序
void CountingSort(vector<int>& dataArray)
{
const int datasize = dataArray.size();
if (datasize <= 0)
return;
//查找出最大和最小值
int min = dataArray[0];
int max = dataArray[0];
for (int i = 1; i < datasize; i++)
{
if (dataArray[i] > max)
max = dataArray[i];
else if (dataArray[i] < min)
min = dataArray[i];
}
//计算桶数量,并投递到不同桶
int bucketNum = max-min+1;
vector<int> bucket(bucketNum, 0);
for (int i = 0; i < datasize; i++)
bucket[dataArray[i]-min]++;
//排序
for (unsigned int i = 0, index = 0; i < bucket.size(); i++)
{
while (bucket[i] > 0)
{
dataArray[index++] = i+min;
bucket[i]--;
}
}
}
//桶排序O(N+M),稳定,分堆处理
void BucketSort(vector<int>& dataArray)
{
const int datasize = dataArray.size();
if (datasize <= 0)
return;
#define BUCKET(i) (i/10)// 桶排序映射函数
//创建桶,并根据映射函数分堆
const int bucketNum = 10;
vector<vector<int>> buckets(bucketNum); //创建bucketNum个桶
for (int i = 0; i < datasize; i++)
{
buckets[BUCKET(dataArray[i])].push_back(dataArray[i]);
}
//开始对每一个桶进行插入排序
for (int i = 0; i < bucketNum; ++i)
{
InsertSort(buckets[i]);
}
//合并
for (int i = 0, index = 0; i < bucketNum; ++i)
{
for (unsigned int j = 0; j < buckets[i].size(); j++)
dataArray[index++] = buckets[i][j];
}
}
void SortTest()
{
const int pArray[] = {10,6,5,4,1,3,2,7,9,8,5,6,9};
const int nArrayCount = sizeof(pArray)/sizeof(pArray[0]);
std::vector<int> dataArray;
cout<<"冒泡排序:"<<endl;
dataArray.assign(pArray, pArray+nArrayCount);
BubbleSort(dataArray);
PrintArray(dataArray);
cout<<"堆排序:"<<endl;
dataArray.assign(pArray, pArray+nArrayCount);
HeapSort(dataArray);
PrintArray(dataArray);
cout<<"堆排序(stl):"<<endl;
dataArray.assign(pArray, pArray+nArrayCount);
HeapSort_STL(dataArray);
PrintArray(dataArray);
cout<<"快速排序:"<<endl;
dataArray.assign(pArray, pArray+nArrayCount);
QSort(dataArray, 0, dataArray.size()-1);
PrintArray(dataArray);
cout<<"快速排序优化(三数取中+插入排序+聚集相等):"<<endl;
dataArray.assign(pArray, pArray+nArrayCount);
QSort_Optimize(dataArray, 0, dataArray.size()-1);
PrintArray(dataArray);
cout<<"插入排序:"<<endl;
dataArray.assign(pArray, pArray+nArrayCount);
InsertSort(dataArray);
PrintArray(dataArray);
cout<<"希尔排序:"<<endl;
dataArray.assign(pArray, pArray+nArrayCount);
ShellSort(dataArray);
PrintArray(dataArray);
cout<<"选择排序:"<<endl;
dataArray.assign(pArray, pArray+nArrayCount);
SelectSort(dataArray);
PrintArray(dataArray);
cout<<"归并排序:"<<endl;
dataArray.assign(pArray, pArray+nArrayCount);
vector<int> tempArray(dataArray.size(), 0);
MergeSort(dataArray, tempArray, 0, dataArray.size()-1);
PrintArray(dataArray);
cout<<"基数排序:"<<endl;
dataArray.assign(pArray, pArray+nArrayCount);
RadixSort(dataArray);
PrintArray(dataArray);
cout<<"桶排序:"<<endl;
dataArray.assign(pArray, pArray+nArrayCount);
BucketSort(dataArray);
PrintArray(dataArray);
cout<<"计数排序:"<<endl;
dataArray.assign(pArray, pArray+nArrayCount);
CountingSort(dataArray);
PrintArray(dataArray);
}
排序算法汇总
最新推荐文章于 2024-09-15 23:24:00 发布