排序算法:快排,插入,希尔,归并,堆,选择,冒泡


#include <iostream>
using namespace std;

//划分函数:将数组划分为大于和小于某元素的两部分
template <typename T>
int partition_job(T *array, int left, int right)
{
	int index = left;
	int pivot = array[index];
	swap(array[index],array[right]);
	for(int i = left; i< right; i++)
	{
		if(array[i] > pivot)
		{
			swap(array[index++], array[i]);
		}//降序
	}
	swap(array[right], array[index]);
	return index;
}


//快速排序:分治法+挖空填空
//快速排序的平均时间复杂度为:O(nlog(n)),每次划分数组整体比较n次,分成两半。
template <typename T>
void qsort_job(T *array, int left, int right)
{
	if(left >= right)
		return ;
	int index = partition_job(array, left, right);
	qsort_job(array, left, index - 1);//做部分
	qsort_job(array, index + 1, right);
}


//插入排序
//平均时间复杂度:O(n2);最好O(n):已排好序;最差O(n2):完全逆序。
/*
原理:
初始:首个元素自成一个有序(已排)序列,其余的记录为无序(待排)序列。
循环:从第二个记录开始,按照记录的大小依次将当前处理的记录插入到其之前的有序序列中。
终止:直至最后一个记录插入到有序序列中为止。
*/
template <typename T>
void insertsort_job(T *data, int size)
{
	for(int i = 1; i < size; i++)
	{
		T key = data[i];
		int j(i-1);
		for(; j >= 0 && data[j] > key; j--) //降序
			data[j+1] = data[j];
		data[j+1] = key;
	}
}

//希尔排序:有间隔的插入排序,间隔逐渐减小,最后间隔为1
//不稳定的,
template <typename T>
void shellsort_job(T *data, size_t size)
{
	for(int gap = size/2; gap > 0; gap /= 2)
	{
		for(int i = gap; i < size; ++i)
		{
			T key = data[i];
			int j = 0;
			for(j = i - gap; j >= 0 && data[j] > key; j -= gap) //降序
				data[j+gap] = data[j];
			data[j+gap] = key;
		}
	}
}

//归并排序
//时间复杂度:O(nlog(n)),取n次堆顶元素,并维护n次堆,每次维护时间为O(log(n))
/*
初始化:将整个序列建立成一个堆。
循环:堆顶元素(最值)与最后一个元素互换,堆的最后一个元素即为最大(以大顶堆为例)记录,完成一次排序
	接着将前N-1个元素(即不包括最大记录)进行大顶堆维护,再将堆顶元素与最后一个元素互换,得到次大值。
	重复以上步骤,直至堆中只剩一个记录,排序结束。
*/
template <typename T>
void Merge(T *array, int low, int mid, int high)
{
	int i, j, k;
	T *temp = (T *)malloc((high - low + 1) * sizeof(T));
	i = low, j = mid + 1, k = 0;
	while(i <= mid && j <= high)	//合并已排好序的前后两半数组元素,以mid为中点分割。
	{
		if(array[i] < array[j])	//升序
			temp[k++] = array[i++];
		else
			temp[k++] = array[j++];
	}
	while(i <= mid)				//若前一半中还有未处理完的元素
		temp[k++] = array[i++];
	while(j <= high)			//若后一半中还有未处理完的元素
		temp[k++] = array[j++];
	for(i = low, j = 0; i <= high; ++i)	//将排好序的元素从临时数组temp输入到array中,并释放temp;
		array[i] = temp[j++];
	free(temp);
}

template <typename T>
void Mergesort(T *array, int low, int high)
{
	int mid;
	if(low < high)
	{
		mid = (low + high) >> 1;
		//递归:二分分解,直至单元素
		Mergesort(array, low, mid);
		Mergesort(array, mid + 1, high);
		//合并:每次合并都是合并两个排好序的子数组
		Merge(array, low, mid, high);
	}
}

//堆排序

//对堆进行调整,使下标从s到m的无序序列成为一个大顶堆
//堆的维护/保持
//一次堆维护的时间复杂度为O(lg(n))
template <typename T>
void HeapAjust(T *array, int s, int m)
{
	int j, temp = array[s];
	//节点s的左子树的下标为:2s+1,右子树下标:2s+2.其实下标为0;
	for(j = 2*s; j <= m; j *=2)
	{
		//选出左右孩子中较大者与父节点比较
		if(j < m && array[j] < array[j+1])
			++j;
		if(temp >= array[j])	//若父节点大于等于左右孩子,则满足大顶堆的定义,跳出循环
			break;
		array[s] = array[j];	//否则用较大的节点替换父节点
		s = j;					//记录下替换父节点的节点下标
	}
	array[s] = temp;
}

//堆的排序(排序过程不断的维护堆)
//http://blog.csdn.net/sdlwlxf/article/details/24645557
template <typename T>
void Heapsort(T *array, int len)
{
	int i;
	// 建堆,堆的叶子节点下标为len/2~len-1,
	//初始化:第一轮循环之前:初始化时只有叶子节点,也是最大堆的根。
	//保持:每次添加一个新节点都对堆进行维护保持。维护时间为O(lg(n))
	//终止:当i=0时,每个都是最大堆的跟。一个堆建立了。
	//建堆的时间复杂度为O(n)而不是O(nlg(n)),详见算法导论 P78.
	for(i = len / 2 - 1; i >= 0; --i)
		HeapAjust(array, i, len - 1);
	//每次将堆顶的元素(数组中最大的元素)与最后元素互换,最大元素就排在最后了。
	//由于换过来的元素不一定满足大顶堆,需要维护一次大顶堆,再转到步骤一,直至循环结束。
	//排序结束,升序。
	for(i = len - 1; i > 0; --i)
	{
		swap(array[0], array[i]);
		HeapAjust(array, 0, i-1);
	}
}

//直接选择排序
//时间复杂度为O(n2),与序列的初始状态无关。
//不稳定:例子:2 2 1
/*
简单选择排序的基本思想:第i趟简单选择排序是指通过n-i次关键字的比较,
从n-i+1个记录中选出关键字最小的记录,并和第i个记录进行交换。共需进行i-1趟比较,直到所有记录排序完成为止。
例如:进行第i趟选择时,从当前候选记录中选出关键字最小的k号记录,并和第i个记录进行交换。
*/
template <typename T>
void SelectSort(T *array, int len)
{
	int i = 0, j = 0, k = 0;
	for(i = 0; i < len - 1; ++i)
	{
		k = i;
		for(j = i+1; j < len; ++j)	//从后面选择一个最小的元素
		{
			if(array[j] < array[k])
				k = j;
		}
		if(k != i)		//与第i个元素交换
			swap(array[i], array[k]);
	}
}

//冒泡排序,下面这并不是真正的冒泡。
template <typename T>
void BubbleSort(T *array, int len)
{
	int i = 0, j = 0;
	for(i = 0; i < len - 1; ++i)
	{
		for(j = i + 1; j < len; ++j)
		{
			if(array[j] < array[i])
				swap(array[i], array[j]);
		}
	}
}


template <typename T>
void BubbleSort2(T *array, int len)
{
	int i = 0, j = 0;
	for(i = 0; i < len - 1; ++i)
	{
		for(j = len - 1; j > i; --j)
		{
			if(array[j] < array[j-1])	//将最小值像水中气泡冒上去。
				swap(array[j], array[j-1]);
		}
	}
}


int main()
{
	int num;
	int arr[200];
	int count=0;

#if 0
	while(cin>>num)
	{
		arr[count++]=num;
	}
	qsort_job(arr, 0, count-1);
	for(int i = 0; i < count; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
#endif

	while(cin>>num)
	{
		arr[count++]=num;
	}
	SelectSort(arr,count);
	for(int i = 0; i < count; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;

	system("pause");

	return 0;
}


/*
参考
http://blog.csdn.net/hackbuteer1/article/details/6568913
*/


原文地址:https://www.cnblogs.com/cnsec/p/3789812.html