sql对数组元素切分_快速排序的一种优化(三项切分的快速排序算法)

首先,先哔哔下什么是快速排序算法。

快速排序由C. A. R. Hoare在1962年提出。基本思想是使一串无序数据,选取其中一条数据,使该数据左边放置全部都是小于该数据的数据,使右边放置大于该数据的数据。这样便完成一趟快速排序,然后可以针对该串数据左边进行下一趟快速排序,右边也进行一趟,这样一次次的进行递归操作,便可得到有序的数据序列。快速排序主要采用的是分治思想

具体算法如下:

public static void QuickSort(int[] arr, int l, int r){
		if(l < r){
			//递归的边界条件,当 L == R时数组的元素个数为1个
			int pivot = arr[l];//最左边的元素作为中轴,L表示left, R表示right
			int i = l+1;
			int j = r;
			//当i == j时,i和j同时指向的元素还没有与中轴元素判断,
			//小于等于中轴元素,i++,大于中轴元素j--,
			//当循环结束时,一定有i = j+1, 且i指向的元素大于中轴,j指向的元素小于等于中轴
			while(i <= j){
				while(i <= j && arr[i] <= pivot){
					i++;
				}
				while(i <= j && arr[j] > pivot){
					j--;
				}
				//当 i > j 时整个切分过程就应该停止了,不能进行交换操作
				//这个可以改成 i < j, 这里 i 永远不会等于j, 因为有上述两个循环的作用
				if(i <= j){
					exchange(arr, i, j);
					i++;
					j--;
				}
			}
			//当循环结束时,j指向的元素是最后一个(从左边算起)小于等于中轴的元素
			exchange(arr, l, j);//将中轴元素和j所指的元素互换
			QuickSort(arr, l, j-1);//递归左半部分
			QuickSort(arr, j+1, r);//递归右半部分
		}
	} 

	private static void exchange(int[] arr , int a , int b){
	//交换数组arr指定的两个元素的位置
	    int temp;
	    temp= arr[a];
	    arr[a] = arr[b];
	    arr[b] = temp;
	}

快速排序算法是一种原地排序,只需要一个很小的栈作为辅助空间,时间复杂度为O(nlogn)。空间复杂度为O(log2n),所以适合在数据集比较大的时候使用。

然后,就开始进入正题:

说说什么事三项切分的快速排序算法。

其实说来也很简单,普通的快速排序是依据选取的固定节点作为一趟排序活动的基准,大于它的放一边,小于它的放另一边,然鹅:你有没有想到要是有其他数据等于你选定的基准咋办?这个时候,就是使用我们今天主角的时候了,把相等的放在中间(与其说放在中间倒不如说交换数组中的位置时放在了一起),大于和小于的分列两边,这样数组分成了三分,比起普通的快速排序,简化了当元素相等时某些元素在数组里面交换来交换去的“逛街”。

本咩咩狠话不多,直接上代码:

public static void QuickSortThreeWay(int[] arr, int l, int r){
    if(l >= r){//递归终止条件,少于等于一个元素的数组已有序
        return;
    }
    int i,j,k,pivot;
    pivot = arr[l]; //首元素作为中间元素
    i = l;
    k = l+1;
    j = r;
     
    while(k <= j){
        if(arr[k] < pivot){
        	exchange(arr, i, k);
            i++;
            k++;
        }else
        if(arr[k] == pivot){
            k++;
        }else{// 遇到arr[k]>pivot的情况,j从右向左扫描
            while(arr[j] > pivot){//arr[j]>pivot的情况,j继续向左扫描
                j--;
                if(j < k){
                    break;
                }
            }
            if(arr[j] == pivot){//arr[j]==pivot的情况
            	exchange(arr, k, j);
                k++;
                j--;
            }else{//arr[j]<pivot的情况
            	exchange(arr, i, j);
                exchange(arr, j, k);
                i++;
                k++;
                j--;
            }
        }
    }
    QuickSortThreeWay(arr, l, i-1); // 对小于pivot的部分进行递归
    QuickSortThreeWay(arr, j+1, r); // 对大于pivot的部分进行递归
}

元素重复率特别高的时候经典的快速排序算法是不适合的。但三向切分的快速排序算法,针对重复率高的时候,避免相同元素来回交换,节省交换次数。对于包含大量重复元素的数组,这个算法将排序时间从线性对数级降到了线性级别。

算法代码来自这位大佬:nullzx - 博客园

389a5c9decf99af910d4d465b7e89a6f.png

end,本咩告辞。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值