快速排序及五种优化(模板)

news/2024/7/7 10:41:03

1、快速排序的基本思想:

快速排序排序使用分治的思想,通过一趟排序将待排序列分割成两部分,其中一部分记录的关键字均比另一部分记录的关键字小。之后分别对这两部分记录继续进行排序,递归地以达到整个序列有序的目

2、快速排序的三个步骤:

(1)选择基准:

在待排序列中,按照某种方式挑出一个元素,作为 “基准”

(2)分割操作:

以该基准在序列中的实际位置,把序列分成两个子序列。此时,在基准左边的元素都比该基准小,在基准右边的元素都比基准大

(3)递归地对两个序列进行快速排序,直到序列为空或者只有一个元素。

3、选择基准的方式

一般取序列的第一个或最后一个元素作为基准基本的快速排序

快排的代码实现:

//划分区间排序
template<typename T>
int partition(T arr[], int startindex, int endindex)
{
	T key = arr[startindex];
	while (startindex < endindex)
	{
		while (startindex < endindex && arr[endindex] >= key)endindex--;
		arr[startindex] = arr[endindex];
		while (startindex < endindex && arr[startindex] <= key) startindex++;
		arr[endindex] = arr[startindex];
	}
	arr[startindex] = key;
	return startindex;
}
template<typename T>
void Quick(T arr[], int s, int e)
{
	//递归算法
	if (s < e)
	{
		int boundindex = partition(arr, s, e);
		Quick(arr, s, boundindex - 1);
		Quick(arr, boundindex + 1, e);
	}
}

template<typename T>
void QuickSort(T arr[], int len)
{
	Quick(arr, 0, len - 1);
}

template<typename T>
void Show(T arr[], int len)
{
	for (int i = 0; i < len; i++)
	{
		std::cout << arr[i] << " ";
	}
	std::cout << std::endl;
}
int main()
{
	int arr[30];
	for (int i = 0; i < 30; i++)
	{
		arr[i] = rand() % 1000;
	}
	int len = sizeof(arr) / sizeof(arr[0]);
	Show(arr, len);
	std::cout << "---------------------" << std::endl;
	QuickSort(arr, len);
	Show(arr, len);
	return 0;
}

4、快速排序的五种优化

(1)随机取基准点 :

若待排序列是部分有序时,固定选取基准使快排效率底下,取待排序列中任意一个元素作为基准

代码实现:

    int arr[30];
    for (int i = 0; i < 30; i++)
    {
    	arr[i] = rand() % 1000;  //随机取基准值
     }
    int len = sizeof(arr) / sizeof(arr[0]);

(2)三数取中(优化有序的数据):

对待排序序列中low、mid、high三个位置上数据进行排序,取中间的那个数据作为基准,并用0下标元素存储基准。

代码实现:

template<typename T>
//三数取中
void FindMiddleNumber(T arr[], int left, int mid, int right)
{
	if (arr[mid] > arr[right])
	{
		Swap(arr, mid, right);
	}
	if (arr[left] > arr[right])
	{
		Swap(arr, left, right);
	}
	if (arr[left] < arr[mid])
	{
		Swap(arr, left, mid);
	}
}

(3)小数据的优化 用插入排序 ,最优情况o(n)

对于很小和部分有序的数组,快排不如插排好。当待排序序列的长度分割到一定大小后,继续分割的效率比插入排序要差,此时可以使用插排而不是快排

代码实现:

template<typename T>
 //插入排序
void insertSort(T arr[], int startindex, int endindex)
{
	int tmp = 0;
	int i = startindex + 1;
	int j = i - 1;
	for (i; i <= endindex; ++i)
	{
		tmp = arr[i];
		for (j = i - 1; j >= startindex && arr[j] > tmp; --j)
		{
			arr[j + 1] = arr[j];
		}
		arr[j + 1] = tmp;
	}
}

(4)聚集优化

重复数据的优化(数据量大,数值小,离散程度小)

(5)非递归优化

没有开栈,清栈,开销小

代码实现:

//非递归快排
if (s < e)
	{
		Stack<int> st;
		int left = s;
		int right = e;
		st.push(right);
		st.push(left);
		while (!st.empty())
		{
			left = st.top(); st.pop();
			right = st.top(); st.pop();
			int boundindex = partition(arr, left, right);
			//left boundindex - 1   boundindex + 1 right;
			if (left < boundindex - 1)
			{
				st.push(boundindex - 1);
				st.push(left);
			}
			if (boundindex + 1 < right)
			{
				st.push(right);
				st.push(boundindex + 1);
			}
		}
	}
}

http://www.niftyadmin.cn/n/4058278.html

相关文章

SCAU 汇编语言 期末复习 (上)

第一章 1.储存单位 存储容量&#xff1a;bit 、Byte、 Word 1 kilobytes210bytes1024bytes 1megabyte(MB)220bytes 1gigabyte(GB)230bytes 1terabyte(TB)240bytes 1petabyte250bytes 1exabyte260bytes 1zettabyte270bytes 1yottabyte280bytes 2个字节&#xff1a; Word &#…

双光耦开关电源电路图_六款简单的开关电源电路设计原理图详解

简单的开关电源电路图(一) 简单实用的开关电源电路图调整C3和R5使振荡频率在30KHz-45KHz。输出电压需要稳压。输出电流可以达到500mA.有效功率8W、效率87%。其他没有要求就可以正常工作。简单的开关电源电路图(二)24V开关电源&#xff0c;是高频逆变开关电源中的一个种类。通过…

序列容器vector和迭代器

一、容器vector vector类模板提供了一种占用连续内存地址的数据结构。这使得它可以高效&#xff0c;直接的利用下标运算符[]访问vector中的任一元素&#xff0c;当一个vecto的内存空间耗尽时&#xff0c;它会分配一个更大的连续空间&#xff08;数组&#xff09;&#xff0c;把…

SCAU 软件工程 期末复习

软件发展阶段 程序设计阶段——50至60年代 程序系统阶段——60至70年代 软件工程阶段——70年代以后 软件工程的生命周期 1.需求分析&#xff08;RequirementsCapture&#xff09; 2.系统分析与设计&#xff08;SystemAnalysis and Design&#xff09; 3.系统实现&#…

年轻工程师怎样修炼成为“高手”

本人做过技术开发工作多年&#xff0c;从焊电路板的小工程师逐渐做到项目经理、研发经理&#xff0c;现在做到总工程师&#xff0c;作为工程师有亲身的感受&#xff0c;作为研发主管&#xff0c;对工程师的性格、心理和知识结构有非常深入的了解&#xff0c;现在把自己的一点感…

冒泡,选择,插入,希尔

/Files/fxllx82/Sorter.rar冒泡演示 转载于:https://www.cnblogs.com/fxllx82/archive/2008/07/17/1245347.html

jQuery简洁大方的登录页面模板

jQueryCSS网站登录模板本模板带验证码在线体验&#xff1a;http://hovertree.com/texiao/jquery/13.htmDemo 2&#xff1a;http://hovertree.com/hvtart/bjae/vgte3y3a.htmDemo 3&#xff1a;http://hovertree.com/hvtart/bjae/dw0f8ytk.htm以下是HTML文件代码&#xff1a; <…

继承与派生(一)

1.继承的作用&#xff1a; 代码复用 继承和派生&#xff0c; 基类和派生类 class Stu : public People 类标识 类名 访问限定符 基类类名 访问限定符一般都为public 2.派生类继承基类的什么东西 除了基类的构造和析构函数以外的所有成员 所以&#xff0c;派生类的构造需要自…