• 算法常识——快速排序


    前言

    什么是快速排序?
    首先问道:比如说从大到小,如何确定一个数组中的一个数已经排好了顺序?
    这个当然有很多种方式,比如说排序的时候最大值在最左边,那么确定了最左边的位置,这就是冒泡的最基本的原理。
    快速排序同样有自己的规则,如果一个数的右边都小于他,左边都大于他,是否这个数不需要变换位置?
    答案是,是的。
    快速排序就是这个原理,快速排序又分为了:
    1.双边循环排序;
    2.单边循环排序;
    这个下面具体会介绍到。
    一些术语:
    基准元素:当前需要确定的元素,也就是对比元素。

    双边循环排序

    参考:程序员小灰这本书

    比如说我要对4进行排序,那么,我需要做的事比较1,因为1<4,那么继续往后2小与4,然后继续往后,4<6,保留当前6的索引。
    然后从右开始,是7,7>4,那么继续往前,然后8也大于,继续,然后是2小于,那么6和2交互位置。然后一直循环下去,当left等于right,那么结束,并且4和left等于right这个位置上交换数字。
    下面使用的递归方式,代码也相当简单。

    static void Main(string[] args)
    {
    	int[] intarr = new int[] {1,6,8,2,3,5,10,48,9 };
    	quickSort(intarr,0,intarr.Length);
    }
    
    public static void quickSort(int []arr,int startIndex,int endIndex)
    {
    	if (startIndex == endIndex)
    	{
    		return;
    	}
    	var baseIndex=changeIndex(arr,startIndex,endIndex);
    	quickSort(arr,startIndex,baseIndex-1);
    	quickSort(arr, baseIndex+1, endIndex);
    }
    
    public static int changeIndex(int []arr,int startIndex,int endIndex)
    {
    	var baseNum = arr[startIndex];
    	// 为什么要从新赋值?startIndex 和 endIndex 是范围的意思,left 和 right 是对比变化的意思。
    	var right = endIndex;
    	var left = startIndex;
    	while (right != left)
    	{
    		while (right<left&&arr[left]<= baseNum)
    		{
    			left++;
    		}
    		while (right<left&& arr[right] > baseNum)
    		{
    			right--;
    		}
    		if (right != left)
    		{
    			var temp = arr[left];
    			arr[left] = arr[right];
    			arr[right] = temp;
    		}
    	}
    	arr[startIndex] = arr[left];
    	arr[left] = baseNum;
    	return left;
    }
    

    单边循环排序

    单边循环 如下图:

    比如说4大于1那么不变,然后4>2同样不变,然后到5,5>4,将这个标记记为mark,就是说这个以后要用一个小的数字来替换,然后4>3,所以用3和5替换掉。
    我一开始是有一个疑问的,如果后面继续是比5大的数呢?mark是否要移动过去,其实是不用的,因为这样的用途是把小于4的尽量往左迁移,这才是真正的用途。
    代码比较简单如下:

    static void Main(string[] args)
    {
    	int[] intarr = new int[] {1,6,8,2,3,5,10,48,9 };
    	quickSortSingle(intarr,0,intarr.Length);
    }
    public static void quickSortSingle(int[] arr, int startIndex, int endIndex)
    {
    	if (startIndex >= endIndex)
    	{
    		return;
    	}
    	var baseIndex = changeSingleIndex(arr, startIndex, endIndex);
    	quickSortSingle(arr, startIndex, baseIndex - 1);
    	quickSortSingle(arr, baseIndex + 1, endIndex);
    }
    
    public static int changeSingleIndex(int[] arr, int startIndex, int endIndex)
    {
    	var baseNum = arr[startIndex];
    	// 为什么要从新赋值?startIndex 和 endIndex 是范围的意思,left 和 right 是对比变化的意思。
    	var left = startIndex;
    	var mark = startIndex;
    	var temp = 0;
    	for (var i=left+1;i<=endIndex;i++)
    	{
    		if (baseNum > arr[i])
    		{
    			mark++;
    			temp = arr[mark];
    			arr[mark] = arr[i];
    			arr[i] = temp;
    			left = mark;
    		}
    	}
    	arr[startIndex] = arr[left];
    	arr[left] = baseNum;
    	return left;
    }
    

    不用递归实现

    static void Main(string[] args)
    {
    	int[] intarr = new int[] {1,6,8,2,3,5,10,48,9 };
    	quickSortSingle(intarr,0,intarr.Length);
    }
    public static void quickSortSingle(int[] arr, int startIndex, int endIndex)
    {
    	Stack stack = new Stack();
    	Tuple<int, int> tuple = new Tuple<int, int>(startIndex, endIndex);
    	stack.Push(tuple);
    		//
    	while (stack.Count!=0)
    	{
    		var oc= (Tuple<int, int>)stack.Pop();
    		if (oc.Item1< oc.Item2)
    		{
    			var baseIndex= changeSingleIndex(arr, oc.Item1, oc.Item2);
    			Tuple<int, int> temp = new Tuple<int, int>(startIndex, baseIndex - 1);
    			Tuple<int, int> temp2 = new Tuple<int, int>(baseIndex +1 , endIndex);
    			stack.Push(temp);
    			stack.Push(temp2);
    		}
    	}
    }
    
    public static int changeSingleIndex(int[] arr, int startIndex, int endIndex)
    {
    	var baseNum = arr[startIndex];
    	// 为什么要从新赋值?startIndex 和 endIndex 是范围的意思,left 和 right 是对比变化的意思。
    	var left = startIndex;
    	var mark = startIndex;
    	var temp = 0;
    	for (var i=left+1;i<=endIndex;i++)
    	{
    		if (baseNum > arr[i])
    		{
    			mark++;
    			temp = arr[mark];
    			arr[mark] = arr[i];
    			arr[i] = temp;
    			left = mark;
    		}
    	}
    	arr[startIndex] = arr[left];
    	arr[left] = baseNum;
    	return left;
    }
    
  • 相关阅读:
    non-blocking I/O
    jetty netty
    Azkaban_Oozie_action
    权限过大 ssh协议通过pem文件登陆
    交易准实时预警 kafka topic 主题 异常交易主题 低延迟 event topic alert topic 内存 算法测试
    flink_action
    netty
    1970 ted codd
    Data dictionary
    mina
  • 原文地址:https://www.cnblogs.com/aoximin/p/12255264.html
Copyright © 2020-2023  润新知