排序算法汇总

#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);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值