(十)1.2_快速排序

在这里插入图片描述

一.相关概念

  快速排序(Quicksort)是对冒泡排序的一种改进。
  快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

如图:
在这里插入图片描述

  1.我们首先把表中的第一个元素作为枢纽,用一个变量暂存并空开那个位置

  2.然后在表中从后往前开始遍历(j–),找到一个比枢纽小的元素放在那个空开的位置,并空开该元素的位置

  3.接着在表中从前往后开始遍历(i++),找到一个比枢纽大的元素放在空开的位置,并空开该元素的位置

  4.就这样反复前后交换,直至表被分割成独立的两部分,其中一部分的所有元素都比另外一部分的所有元素都要小(i=j时),然后把枢纽元素放在空开的位置(即i位置或j位置)

  5.这样枢纽就把表分割成了两个子表,然后我们同样对子表分别做1,2,3,4操作,直到子表不可被分割(小于等于1个元素的表),最后整个序列便排序完成

如图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q9XVKjAG-1593866840878)(http://www.th7.cn/d/file/p/2015/08/27/a42438122d1f874cce061a57a0206e7c.jpg)]


二.思路分析

  很多书上写的快速排序算法都使用了递归,但是如果排序数据很多,递归堆栈会占用很大的内存,使得程序被终止,所以我这里教大家使用非递归算法实现快速排序,其实就是使用栈来实现递归转化为非递归.

  1.首先我们需要一个存储表高低端位置序号的栈,初始我们把表的高低端位置(首尾位置)序号入栈,也就是入栈两个位置序号

  2.我们用一个循环(栈非空就执行循环),循环里这样操作:出栈一个表(子表)的高低端位置,也就是出栈两个位置序号,然后对改子表进行排序分割

  3.分割完成后,表被一分为二,然后分别入栈两个子表的高低端位置,也就是入栈四个位置序号
4.循环1,2,3,直到栈空,排序完成


三.代码实现

注意:顺序表中零单元不用,从索引1开始存储元素

//非递归快速排序(排列为递增序列)
void QuickSort(SqList &L)
{	
    //快速排序的非递归方法,用栈来保存每个子表的高低端位置 
    int MAX=L.length+2;     //在最坏情况下栈需要的最大内存 
    int *stack=(int*)malloc(sizeof(int)*MAX);       //构建栈 
	int top=0;            //栈顶 
	int low=1,high=L.length;   //低端位置,高端位置 
	int pivotkey;          //枢纽  
	stack[top++]=high;   //初始高端位置入栈
	stack[top++]=low;    //初始低端位置入栈
	while(top!=0)        //栈非空循环 
   {    
   	    low=stack[--top];   //要处理的子表的低端位置出栈
   	    high=stack[--top];  //要处理的子表的高端位置出栈
	    L.elem[0]=L.elem[low];     //用子表的第一个记录作为枢纽记录,零单元作为辅助单元暂存枢纽 
	    pivotkey=L.elem[low];  //枢纽记录关键字	    
	    int head=low;          //记录首端 
	    int end=high;          //记录末端  
	    while(low<high)		  //分割子表操作 
	    {		
			while(low<high&&L.elem[high]>=pivotkey) 
			high--;                   //从后往前找到一个比枢纽关键字小的数据 
			L.elem[low]=L.elem[high];   //把比枢纽小的数据项放在低端 
			while(low<high&&L.elem[low]<=pivotkey) 
			low++;                   //从前往后找到一个比枢纽关键字大的数据 
			L.elem[high]=L.elem[low];  //把比枢纽大的数据项放在高端		 	
	    }
		L.elem[low]=L.elem[0];        //此时low=high,low为枢纽的插入位置,所以也可写成L.elem[high]=L.elem[0];		
		if(head>=end)                 //如果该子表不能再分割(即该子表小于等于1个单元),不再进行高低端位置入栈操作 
	    	continue; 
	    stack[top++]=end;      //枢纽右侧的子表高端位置入栈
		stack[top++]=low+1;    //枢纽右侧的子表低端位置入栈	
		stack[top++]=low-1;    //枢纽左侧的子表高端位置入栈
		stack[top++]=head;     //枢纽左侧的子表低端位置入栈				
   }
   free(stack);          //释放栈内存 
}

操作结果:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值