直插,快排,堆排,归并--四种排序讲解

一:直接插入排序

直接插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。

概念很简单,直接看代码:

#include<iostream>
#include<algorithm>
using namespace std;
void InsertSort(int _arry[]);

int main()
{
	int arry[10] = { 2,0,6,9,7,4,1,3,5,4 };
	InsertSort(arry);
	for each (auto & x in arry)
	{
		cout << x << " ";
	}
	cout << endl;
	return 0;
}

void InsertSort(int _arry[])//升序
{
	int temp;
	for (int i = 1; i < 10; i++)
	{
		if (_arry[i] < _arry[i - 1])
		{
			temp = _arry[i];
			int j;

			for (j = i - 1; j >= 0 && temp < _arry[j]; j--)
				_arry[j + 1] = _arry[j];

			_arry[j + 1] = temp;
		}
	}
}



二:快速排序

快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。快速排序可以说是很重要,在笔试也经常拿来判断一个程序员的基础编码水平。关于快速排序的理解,可以参考这篇文章,讲解的很易懂,http://developer.51cto.com/art/201403/430986.htm

下面附上我的代码:

#include<iostream>
#include<algorithm>
using namespace std;

int arry[10];

void QuickSort(int left, int right);

int main()
{
	for each (auto x in arry)
		cin >> x;
	
	QuickSort(0, 9);//快排
	
	for each(auto & x in arry)
		cout << x << " ";
	cout << endl;
	
	return 0;
}

void QuickSort(int left, int right)
{
	if (!(left<right))
		return;

	int i = left;
	int j = right;
	int base = arry[i];
	while (i < j)
	{
		while (i < j&&arry[j] >= base)//先做右边的
			j--;
		while (i < j&&arry[i] <= base)//然后做左边的,注意顺序
			i++;

		if (i < j)
		{
			int temp = arry[i];
			arry[i] = arry[j];
			arry[j] = temp;
		}
	}
	arry[left] = arry[i];
	arry[i] = base;
	
	QuickSort(left, i - 1);
	QuickSort(i + 1, right);
}



三:堆排序

堆排序的内容有点多,写这篇博客的目的也不是教学初学者,只是做个笔记。其实这四个排序,要写出来是不难的,这四个排序的概念在数据结构课本上都有概念上的讲解,无论是否初次涉及这个算法,我觉得认真看的话,都是可以理解的。当然,如果你是一个好学的孩子,已经提前学到这个算法,而又苦于找不到好的概念讲解和完整的代码参考,我就提供几个链接来弥补这篇博客上的算法概念分析的不足, http://bubkoo.com/2014/01/14/sort-algorithm/heap-sort/,http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html

#include<iostream>  
#include<utility>

using namespace std;

int arry[] = { 2,3,9,5,1,7,6,4,0,8 };

/* 已知arry[s....m]的值除arr[s]之外均满足堆的定义,本函数调整arry[s],使arr[s...m]成一个大顶堆 */
void HeapAdjust(int s, int m)
{
	int rc = arry[s];

	for (int i = s * 2; i <= m; i*=2)
	{
		if (i < m&&arry[i] < arry[i + 1]) i++;
		if (rc >= arry[i]) break;

		arry[s] = arry[i];
		s = i;
	}

	arry[s] = rc;
}

/* 升序排序 */
void HeapSort(int & len)
{
	for (int i = len / 2; i >= 0; i--)
		HeapAdjust(i, len - 1);
	for (int i = len - 1; i > 0; i--)
	{
		swap(arry[0], arry[i]);//将大值依次放在后面
		HeapAdjust(0, i - 1);
	}
}
int main()
{
	int len = sizeof(arry) / sizeof(int);

	HeapSort(len);

	for each(auto x in arry)
		cout << x << " ";//0 1 2 3 4 5 6 7 8 9
	cout << endl;

	return 0;
}



四:归并排序

首先考虑下如何将将两个有序数列合并。这个非常简单,只要比较两个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。

而归并排序就是递归的去做上面的事情。

直接看代码。

#include<iostream>
#include<algorithm>

using namespace std;

/* 把有序的arry[start...mid]和有序的arry[mid+1...end]合并 */
void Merge(int* arry, int* assit, int start, int mid, int end)
{
	int i, j;
	int k = start;
	for (i = start, j = mid + 1; i <= mid&&j <= end; )
		assit[k++] = (arry[i] > arry[j]) ? arry[j++] : arry[i++];

	//将剩余的数依次放入assit中
	while (i <= mid)
		assit[k++] = arry[i++];
	while (j <= end)
		assit[k++] = arry[j++];

	for (i = start; i <= end; i++)
		arry[i] = assit[i];
}

/* 升序--对arry[start....end]进行归并排序 */
void MergeSort(int* arry, int* assit, int start, int end)
{
	if (start < end)
	{
		int mid = (start + end) >> 1;
		MergeSort(arry, assit, start, mid);
		MergeSort(arry, assit, mid + 1, end);
		Merge(arry, assit, start, mid, end);
	}
}
int main()
{
	int* arry;
	int* assit;//辅助

	arry = new int[10]{ 2,3,9,5,1,7,6,4,0,8 };
	assit = new int[10];
	
	MergeSort(arry, assit, 0, 9);

	for_each(arry, arry + 10, [](int x) {cout << x << " "; });
	
	cout << endl;

	delete[]arry;
	delete[]assit;

	return 0;
}


五:四种排序的分析

下面从算法的稳定性和效率两方面来讲:


1.稳定性

什么叫稳定?百度百科解释为:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;否则称为不稳定的。

那么在上述算法中,哪个是稳定的?哪个是不稳定的?

直接插入排序-->稳定

快速排序-->不稳定

堆排序-->不稳定

归并排序-->稳定


2.效率

排序方法 平均时间 最坏情况 辅助存储
直接插入 O(n*n) O(n*n) O(1)
快速排序 O(n*logn) O(n*n) O(logn)
堆排序 O(n*logn) O(n*logn) O(1)
归并排序 O(n*logn) O(n*logn) O(n)







你可能感兴趣的:(数据结构,C++,排序)