常用排序算法总结

整理了下一些常用的排序算法。原文访问链接:http://www.nicemxp.com/articles/16

一、冒泡排序

冒泡排序:一排n个元素的序列,通过两两比较交换位置保持大的(或者小的)在右侧,这样经过n-1轮这样的操作完成排序。

源码:

#define SWAP(a,b) {a=a+b;b=a-b;a=a-b;}

// 冒泡排序
void BubbleSort(int src[], int n)
{
	for (int i = 0; i <= n - 2; i++)
	{
		for (int j = 0; j <= n - 2 - i; j++)
		{
			if (src[j] > src[j + 1])
			{
				SWAP(src[j], src[j+1])
			}
		}
	}
}

空间复杂度:O(1)

时间复杂度:最好:O(n),最坏O(n^2),平均O(n^2)

冒泡排序是稳定排序

二、选择排序

选择排序:一排n个元素的序列,每次通过两两比较,选出最大的索引与最右侧的元素交换,这样第一轮排出最大的元素在最右侧,第二轮选出第二大的元素在最右侧左移一个元素,这样经过n-1轮完成排序。

源码:

#define SWAP(a,b) {a=a+b;b=a-b;a=a-b;}

// 选择排序
void SelectionSort(int src[], int n)
{
	for (int i = 0; i <= n - 2; i++)
	{
		int key = 0;
		for (int j = 0; j <= n - 2 - i; j++)
		{
			if (src[key] < src[j])
				key = j;
		}
		if (src[key]> src[n - 1 - i])
		{
			SWAP(src[key], src[n-1-i])
		}
	}
}

空间复杂度:O(1)

时间复杂度:最好:O(n),最坏O(n^2),平均O(n^2)

选择排序是不稳定排序

三、插入排序

插入排序:一排n个元素的序列,从左向右遍历,遍历的每一个元素与它左侧元素逐一比较,找到刚好小于它的元素插入到后面,比他大的逐一向右侧移动一个元素,直至遍历完毕完成排序。

源码:

// 插入排序
void InsertSort(int src[], int n)
{
	for (int pt = 1; pt < n; pt++)
	{
		int key = src[pt];
		int idx = pt - 1;
		while (idx >= 0 && src[idx] > key)
		{
			src[idx + 1] = src[idx];
			idx--;
		}
		src[idx + 1] = key;
	}
}

空间复杂度:O(1)

时间复杂度:最好:O(n),最坏O(n^2),平均O(n^2)

插入排序是稳定排序

四、快速排序

快速排序:快速排序将n个元素的序列通过递归的方法,每次规定一个关键值,将小于等于关键值的元素放置到关键值左侧,大于关键值的元素放置到关键值右侧,这样直到递归完毕完成排序。

源码:

#define SWAP(a,b) {a=a+b;b=a-b;a=a-b;}

//快速排序
void QuickSort(int src[],int begin, int end)
{
	if (begin >= end)
		return;
	int key = src[begin];
	int l = begin;
	int r = end;
	while (l < r)
	{
		while (src[l] <= key && l < r)
			l++;
		while (src[r] > key && r > l)
			r--;
		if (r > l)
			SWAP(src[l], src[r])
	}

	if (r > begin)
		SWAP(src[begin], src[r])

	QuickSort(src, begin, r-1);
	QuickSort(src, r+1, end);
}

空间复杂度:O(log2n)

时间复杂度:最好:O(nlog2n),最坏:O(n^2),平均:O(nlog2n)

快速排序是不稳定排序

五、归并排序

归并排序:一个n个元素的序列,进行递归,每次递进时平均拆分成两个序列,然后对拆分后的序列进行排序,最后对排好序的两个序列进行合并。这样递归结束完成排序。

源码:

// 归并排序
void Combine(int src[], int begin, int end)
{
	int mid = (begin + end) / 2;
	int p = begin;
	int q = mid + 1;
	int k = 0;
	int* tmp = new int[end - begin + 1];
	while (p <= mid && q <= end)
	{
		if (src[p] <= src[q])
			tmp[k++] = src[p++];
		else
			tmp[k++] = src[q++];
	}
	while (p <= mid)
		tmp[k++] = src[p++];
	while (q <= end)
		tmp[k++] = src[q++];
	//复制到原数组
	for (int i = 0; i < end - begin + 1; i++)
	{
		src[begin + i] = tmp[i];
	}

	delete[] tmp;
}

void MergeSort(int src[], int begin, int end)
{
	if (begin >= end)
		return;
	
	int mid = (begin + end) / 2;
	MergeSort(src, begin, mid);
	MergeSort(src, mid + 1, end);

	Combine(src, begin, end);
}

空间复杂度:O(nlog2n)

时间复杂度:最好,最坏,平均:O(nlog2n)

归并排序是稳定排序

六、堆排序

堆排序:堆排序是将一个n个元素的序列描述成一个二叉树的形式,建立大根堆(每个根节点都不小于它的叶子节点的值),或者小根堆(每个根节点都不大于它的叶子节点的值),然后通过n-1次调堆完成排序。

源码:

#define LEFTCHILD(i) (i * 2 + 1)
#define RIGHTCHILD(i) (i * 2 + 2)
#define SWAP(a,b) {a=a+b;b=a-b;a=a-b;}

//调堆
void MaxHeap(int src[], int heapsize, int pos)
{
	int lastest = pos;
	while (1)
	{
		int l = LEFTCHILD(pos);
		int r = RIGHTCHILD(pos);
		if (l < heapsize && src[lastest] < src[l])
			lastest = l;
		if (r < heapsize && src[lastest] < src[r])
			lastest = r;
		if (lastest == pos)
			break;
		SWAP(src[pos], src[lastest]);

		pos = lastest;
	}
}
// 堆排序
void HeapSort(int src[], int heapsize)
{
	//建堆
	for (int k = heapsize / 2 - 1; k >= 0; k--)
	{
		MaxHeap(src, heapsize, k);
	}
	//调堆
	for (int k = heapsize - 1; k > 0; k--)
	{
		SWAP(src[0], src[k]);
		heapsize--;
		MaxHeap(src, heapsize, 0);
	}
}

空间复杂度:O(1)

时间复杂度:最好:O(nlog2n),最坏:O(nlog2n),平均:O(nlog2n)

堆排序是不稳定排序

七、希尔排序

希尔排序:希尔排序是插入排序的一种优化,是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,就变成了直接插入排序,算法终止。

源码:

//希尔排序
void ShellSort(int src[], int n)
{
	for (int gap = n / 2; gap > 0; gap = gap / 2)
	{	
		for (int pt = gap; pt < n; pt++)
		{
			int key = src[pt];
			int idx = pt - gap;
			while (idx >= 0 && src[idx] > key)
			{
				src[idx + gap] = src[idx];
				idx = idx - gap;
			}
			src[idx + gap] = key;
		}
	}
}

空间复杂度:O(1)

时间复杂度:最好,平均:O(nlog2n),最坏O(n^2)

希尔排序是不稳定排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值