复习一下快速排序(带非递归)


快速排序的核心思路和挖坑填坑和分治法。
首先取一个枢纽值,枢纽值一般选取分段两边和中间数字三者的中间项。
这时就先挖坑,把枢纽值所在项和第一项交换,成为第一项。然后再第一项挖坑,并且保存第一项所在的枢纽值。

=========================================
然后该项和最后项往前进行逐个判断,出现小于枢纽值的项就和坑交换位置。
交换过一次后,再从第一个项往前找大于枢纽值的项和坑交换位置。

=========================================
不断的交换的结果是枢纽值被移动到了中间项
之后再对枢纽值两边进行递归分治,直到排序完成

using System;

namespace DigPro
{
    class Program
    {
        static void Main(string[] args)
        {
            Dig dig = new Dig();
            dig.DigSort(dig.im, 0, dig.im.Length - 1);
            dig.Cout();
        }
    }
    class Dig
    {
        public int[] im = { 70, 8, 6, 99, 4, 56, 45, 3, 56, 78, 1 };
        //lastDig表示上一次坑的位置,也就是枢纽值最后所在的位置。
        //第一次为0,如果不想取第一个数就把想取得枢纽值和第一个交换,digLength表示末位置的项
        public void DigSort(int[] s, int lastDig, int digLength)
        {
            //if (digLength - lastDig > 3)
            //    GetMid(ref s[lastDig], ref s[(lastDig + digLength) / 2], ref s[digLength]);
            int i = lastDig, j = digLength;
            int X = s[i];
            while (i < j)
            {
                while (i < j && s[j] >= X) j--;
                if (i < j) { s[i] = s[j]; i++; }
                while (i < j && s[i] <= X) i++;
                if (i < j) { s[j] = s[i]; j--; }
            }   //这里不难看出,跳出循环时,i=j,所以递归里没有出现j
            s[i] = X;
            if (lastDig < digLength)
            {
                DigSort(s, lastDig, i - 1);
                DigSort(s, i + 1, digLength);
            }
        }
        public void Cout()
        {
            for (int i = 0; i < im.Length; i++)
            {
                Console.Write(im[i] + ",");
            }
        }
        public void GetMid(ref int x1, ref int x2, ref int x3)
        {
            //{ int temp = a[j]; a[j] = a[i]; a[i] = temp; }
            if ((x1 <= x2 && x1 >= x3) || (x1 <= x3 && x1 >= x2))
                return;
            else if ((x2 <= x1 && x2 >= x3) || (x2 <= x3 && x2 >= x1))
            { int temp = x2; x2 = x1; x1 = temp; }
            else
            { int temp = x3; x3 = x1; x1 = temp; }
        }
    }
}

该函数用于取某一区间头尾和中间项,得到3个项中的中间值,作为枢纽值进行快速排序

============================================================

因为在Unity里需要用到排序,测试了下发现用递归实现在unity里太慢了……一点都不快速=,=

偷懒是不好的,所以稍微改了一下。

所有的递归都可以用栈去存储数据从而做到循环代替递归。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CityBuild : MonoBehaviour
{
    public void Start()
    {
        int[] im = { 70, 8, 6, 99, 4, 56, 45, 3, 56, 78, 1 };
        QuickSort(im);
        foreach (int x in im)
        {
            Debug.Log(x + ";");
        }
    }

    public void QuickSort(int[] date)
    {
        Stack<int> indexStack;
        int startIndex = 0;
        int endIndex = date.Length - 1;
        if (!(startIndex < endIndex))
            return;
        int digIndex = 0;
        indexStack = new Stack<int>();
        indexStack.Push(endIndex);
        indexStack.Push(startIndex);
        while (indexStack.Count != 0)
        {
            startIndex = indexStack.Pop();
            endIndex = indexStack.Pop();
            digIndex = partition(date, startIndex, endIndex);
            if (startIndex < digIndex - 1)
            {
                indexStack.Push(digIndex - 1);
                indexStack.Push(startIndex);
            }
            if (endIndex > digIndex + 1)
            {
                indexStack.Push(endIndex);
                indexStack.Push(digIndex + 1);
            }
        }

    }
    private int partition(int[] date, int startIndex, int endIndex)
    {
        if (endIndex - startIndex > 3)
            GetMid(ref date[startIndex], ref date[(startIndex + endIndex) / 2], ref date[endIndex]);
        int i = startIndex, j = endIndex;
        int X = date[i];
        while (i < j)
        {
            while (i < j && date[j] >= X) j--;
            if (i < j) { date[i] = date[j]; i++; }
            while (i < j && date[i] <= X) i++;
            if (i < j) { date[j] = date[i]; j--; }
        }   //这里不难看出,跳出循环时,i=j,所以递归里没有出现j
        date[i] = X;
        //这里返回一个i,此时i=j,用于入栈,注意先入end方便出栈
        return i;
    }
    private void GetMid(ref int x1, ref int x2, ref int x3)
    {
        //{ int temp = a[j]; a[j] = a[i]; a[i] = temp; }
        if ((x1 <= x2 && x1 >= x3) || (x1 <= x3 && x1 >= x2))
            return;
        else if ((x2 <= x1 && x2 >= x3) || (x2 <= x3 && x2 >= x1))
        { int temp = x2; x2 = x1; x1 = temp; }
        else
        { int temp = x3; x3 = x1; x1 = temp; }
    }
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值