八大排序(简单总结)

八大排序

冒泡排序(升序)

思想:两两相比,大的往后移,每轮结束数据中最大的数冒到数组最后

优缺点:稳定、不需要辅助空间;但效率低(每次都需要交换数据)

复杂度:(时间换空间,不需要额外空间)

平均时间复杂度:O(n²) 、 最好(已经有序的情况):O(n)、最差(正好倒序的情况):O(n^2)

从前往后冒泡
template<class T>
void PopSort(T * const pdata, size_t size, bool IsUp = true)
{
	T swapdata;
	for (int i = 0; i < size - 1; ++i)
	{
		for (int j = 0; j < size - 1 - i; ++j)
		{
			if (pdata[j] > pdata[j + 1])
			{
				swapdata = pdata[j];
				pdata[j] = pdata[j + 1];
				pdata[j + 1] = swapdata;
			}
		}
	}
}
从后往前冒泡
template<class T>
void PopSort(T * const pdata, size_t size, bool IsUp = true)
{
	T swapdata;
	for (int i = 0; i < size - 1; ++i)
	{
		for (int j = size - 1; j > i; --j)
		{
			if (pdata[j] < pdata[j - 1])
			{
				swapdata = pdata[j];
				pdata[j] = pdata[j - 1];
				pdata[j - 1] = swapdata;
			}
		}
	}
}
选择排序(升序)

思想:选取一个元素 ,依次比较,选取小于的记录下标,一次循环结束后交换元素

优缺点:相比于冒泡排序,选择的交换次数更少(比较次数没有减少),但是不稳定

复杂度

时间复杂度:O(n²)
空间复杂度:O(1)

代码实现
template<class T>
void SelectSort(T * const pdata, size_t size, bool IsUp = true)
{
	T swapdata;
	int limitindex = 0;		//极限下标
	for (int i = 0; i < size - 1; ++i)
	{
		limitindex = i;
		for (int j = i + 1; j < size; ++j)
		{
			if (pdata[limitindex] > pdata[j])
			{
				limitindex = j;		//记录交换下标
			}
		}
		swapdata = pdata[limitindex];
		pdata[limitindex] = pdata[i];
		pdata[i] = swapdata;
	}
}
插入排序(升序)

思想:把n个待排序的元素看成为一个有序表和一个无序表。开始时有序表中只包含1个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,将它插入到有序表中的适当位置,使之成为新的有序表,重复

优缺点:快速但是不稳定(比较次数不一定,比较次数越多,插入点后的数据移动越多)但是在链表中插入排序具有绝对优势

复杂度

时间复杂度度:最好:O(n)最坏:O(n²)

图解

在这里插入图片描述

代码实现
template<class T>
void InsertSort(T * const pdata, size_t size, bool IsUp = true)
{
	T tempdata;
	for (int i = 1; i < size; ++i)
	{
		tempdata = pdata[i];
		int j;
		for (j = i - 1; j >= 0; --j)
		{
			if (tempdata < pdata[j])		//后面小
			{
				pdata[j + 1] = pdata[j];
			}
			else
			{
				break;
			}
		}
		pdata[j + 1] = tempdata;
	}
}
归并排序(升序)

思想:将原序列不断进行二分,直至只有一个元素,得到n个只含有一个元素的序列,再将这n个需序列不断地两两合并,最终得到一个有序的序列。

优缺点:效率高,稳定,但需要O(n)的空间复杂度(略高)

复杂度

时间复杂度:O(nlogn)

代码实现(使用递归方式)
#ifndef SAFE_DELARR
#define SAFE_DELARR(p){if(p!=nullptr){delete []p;p=nullptr;}}
#endif

template<class T>
void MergeSort(T * const pdata, size_t size, bool IsUp = true)
{
	if (size > 1)
	{
		//分割至每个序列只有一个元素
		size_t asize = size / 2;
		size_t bsize = size - asize;

		T * pAbuffer = new T[asize];
		T * pBbuffer = new T[bsize];
		memcpy(pAbuffer, pdata, sizeof(T)*asize);
		memcpy(pAbuffer, pdata + asize , sizeof(T)*bsize);
		MergeSort(pAbuffer, asize, IsUp);		//递归
		MergeSort(pBbuffer, bsize, IsUp);

		size_t aindex = 0, bindex = 0, dataindex = 0;
		if (IsUp)
		{
			//向上归并
			while ((aindex < asize) && (bindex < bsize))
			{
				if (pAbuffer[aindex] < pBbuffer[bindex])
				{
					pdata[dataindex] = pAbuffer[aindex];
					++aindex;
				}
				else
				{
					pdata[dataindex] = pBbuffer[bindex];
					++bindex;
				}
				++dataindex;
			}
		}

		while (aindex < asize)
		{
			pdata[dataindex] = pAbuffer[aindex];
			++aindex;
			++dataindex;
		}
		while (bindex < bsize)
		{
			pdata[dataindex] = pBbuffer[bindex];
			++bindex;
			++dataindex;
		}

		SAFE_DELARR(pBbuffer);
		SAFE_DELARR(pAbuffer);
	}
}

使用非递归方式
template<class T>
void MergeSort2(T * const pdata, size_t size, bool IsUp = true)
{
	size_t blocksize = 2;
	size_t smallblocksize = blocksize / 2;
	T * ptempdata = new T[size];

	if (IsUp)
	{
		while (blocksize < 2 * size)
		{
			memcpy(ptempdata, pdata, sizeof(T)*size);

			for (size_t blockheadindex = 0; blockheadindex < size; blockheadindex += blocksize)
			{
				size_t aindex = blockheadindex;
				size_t bindex = blockheadindex + smallblocksize;
				size_t dataindex = blockheadindex;

				while ((aindex < (blockheadindex + smallblocksize)) && (aindex < size) &&
					(bindex < (blockheadindex + blocksize)) && (bindex < size))
				{
					if (ptempdata[aindex] < ptempdata[bindex])
					{
						pdata[dataindex] = ptempdata[aindex];
						++aindex;
					}
					else
					{
						pdata[dataindex] = ptempdata[bindex];
						++bindex;
					}
					++dataindex;
				}

				while (aindex < (blockheadindex + smallblocksize) && (aindex < size))
				{
					pdata[dataindex] = ptempdata[aindex];
					++aindex;
					++dataindex;
				}

				while ((bindex < (blockheadindex + blocksize)) && (bindex < size))
				{
					pdata[dataindex] = ptempdata[bindex];
					++bindex;
					++dataindex;
				}
			}
		
			smallblocksize = blocksize;
			blocksize *= 2;
		}
	}

	if (ptempdata != nullptr)
	{
		delete[]ptempdata;
		ptempdata = nullptr;
	}
}
基数排序【桶排序】(升序)

思想:基数排序是根据数位来进行排序的,从个位开始,按照每一位的数进行比较排序

优缺点:稳定,效率极高;但使用范围受限(只适用整数)

复杂度

时间复杂度:O(n*k)
空间复杂度:O(n+k)

图解

在这里插入图片描述

代码实现
template<class T>
void RadixSort(T * const pdata, size_t size, bool IsUp = true, size_t radixtime = 5)
{
	T *pBuffer[10] = { nullptr };
	int BufferDataNum[10] = { 0 };
	for (int i = 0; i < 10; ++i)
	{
		pBuffer[i] = new T[size];		//存在所有元素都在一个桶内的情况
	}

	size_t bufferindex = 0;		//第几个桶
	size_t numbase = 1;
	for (size_t rt = 0; rt < radixtime; ++rt)
	{
		for (int i = 0; i < 10; ++i)
		{
			BufferDataNum[i] = 0;
		}

		for (size_t s = 0; s < size; ++s)
		{
			bufferindex = pdata[s] / numbase % 10;
			pBuffer[bufferindex][BufferDataNum[bufferindex]] = pdata[s];
			++BufferDataNum[bufferindex];
		}

		//倒回去
		int dataindex = 0;
		if (IsUp)
		{
			for (int bindex = 0; bindex < 10; ++bindex)
			{
				for (int bn = 0; bn < BufferDataNum[bindex]; ++bn)
				{
					pdata[dataindex++] = pBuffer[bindex][bn];
				}
			}
		}
		numbase *= 10;
	}

	for (int i = 0; i < 10; ++i)
	{
		SAFE_DELARR(pBuffer[i]);
	}
}
希尔排序(升序)

思想:希尔排序是把数据序列按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的数据个数越来越多,当增量减至1时,整个文件恰被分成一组,整个数据序列就已经排序好了,算法便终止。(内部是插入排序)

优缺点:数据移动量少,效率高;但不稳定。

复杂度

时间复杂度:O(n^1.5)

图解

在这里插入图片描述

代码实现
template<class T>
void ShellSort(T * const pdata, size_t size, bool IsUp = true)
{
	size_t step = size / 2;		//确定步长
	T temp;

	if (IsUp)
	{
		while (step > 0)
		{
			for (size_t listheadindex = 0; listheadindex < step; ++listheadindex)
			{
				//内部就是插入排序
				for (size_t i = listheadindex + step; i < size; i += step)
				{
					temp = pdata[i];
					int j;
					for (j = i - step; j >= 0; j -= step)
					{
						if (temp < pdata[j])
						{
							pdata[j + step] = pdata[j];
						}
						else
						{
							break;
						}
						pdata[j + step] = temp;
					}
				}
				step /= 2;		//缩减步长
			}
		}
	}
}
快速排序(升序)

思想

1.选定first和last,并取first或last位置值为key(这里取first位置值为key);
2.从last位置开始,一个个向前(向first位置)取值和key值比较,如果大于等于key值,last位置数据不变,last前移.如果小于 key值的话.将last位置的数据赋值给first位置,结束当次last搜索;
3.从first位置开始,一个个向后(向last位置)取值和key值比较.如果小于等于key值,first位置的数据不变,fisrt后移.如果大于key值的话,将first位置的数据赋值给last位置,结束当次first搜索.
4.重复第二,三步,并在first>=last时结束,同时把key值还原到first位置。
以上完成的是一个key值的排序.以上流程一定确定好了key值的位置,同时key值将整个数据列分成左右两段.左段为(0 ~ first-1),左段的数一定都小于key,右段为(first+1 ~ last),右段的数一定都大于key.分别对左右两段再次进行快速排序,直到段大小为1为止.

优缺点:数据移动少,快速;但不稳定,当数组本身接近有序时,此时排序性能很差

复杂度

时间复杂度:最好:O(nlog2n),最坏:O(n²)

图解

在这里插入图片描述

代码实现
template<class T>
void _QuickSort(T * const pdata, int first, int last, bool IsUp)
{
	if (first < last)
	{
		T key = pdata[first];
		int _first = first;
		int _last = last;

		if (IsUp)
		{
			while (_first > _last)
			{
				while (_first > _last)
				{
					if (key > pdata[_last])
					{
						pdata[_first] = pdata[_last];
						break;
					}
					else
					{
						--_last;
					}
				}
				while (_first > _last)
				{
					if (key < pdata[_first])
					{
						pdata[_last] = pdata[_first];
						break;
					}
					else
					{
						++_first;
					}
				}
			}
		}
		pdata[_first] = key;
		//递归
		_QuickSort(pdata, first, _first - 1, IsUp);
		_QuickSort(pdata, _first + 1, last, IsUp);
	}
}
template<class T>
void QuickSort(T * const pdata, size_t size, bool IsUp = true)
{
	_QuickSort(pdata, 0, size - 1, IsUp);		//调用
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值