几种常用排序算法

6 篇文章 0 订阅

其实最重要还是理解,不用刻意去记代码怎么写的。

选择排序:

每次从数组里选出一个最小的放在最前面,以此类推。

冒泡排序:

从后往前,两两交换,每次把最小的一个放到最前面。

插入排序:

每次把未排序的下一个元素插入到已排序的数组中。

希尔排序:

 

也叫缩小增量排序,每次跨度为数组总长度/2,以此类推。

快速排序:

找一个基准值,把比基准值大的都放数组右边,把比基准值小的,都放数组左边,而且依次递归。

堆排序:

可以实现部分排序,比如想在1000个数中找出最大的100个数,这个时候,没必要把剩下900个数都排序。

原理为:

       a.将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;

  b.将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;

  c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。

(个人强烈建议,当数据量特别大时,快速排序和希尔排序,所用时间要远远小于前面几种排序方式)

附上各种排序算法的复杂度,虽然讲暂时不太清楚为什么是这个值

排序法

最差时间分析平均时间复杂度稳定度空间复杂度
冒泡排序O(n2)O(n2)稳定O(1)
快速排序O(n2)O(n*log2n)不稳定O(log2n)~O(n)
选择排序O(n2)O(n2)稳定O(1)
二叉树排序O(n2)O(n*log2n)不一顶O(n)

插入排序

O(n2)O(n2)稳定O(1)
堆排序O(n*log2n)O(n*log2n)不稳定O(1)
希尔排序OO不稳定O(1)

多的就不说了,直接上代码。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using Debug = UnityEngine.Debug;


public class SortManager : MonoBehaviour
{
    private List<int> _oldInts = new List<int>() { 57, 44, 11, 45, 67, 888, 90, 53 };

    private List<int> intlists;
    private List<string> stringlists;
    private int? num;
    // Use this for initialization
    void Start()
    {

    }

    private void Sort(Action ac)
    {
        _oldInts.Clear();
        for (int i = 0; i < 10000; i++)
        {
            int tem = UnityEngine.Random.Range(0, 10000);
            _oldInts.Add(tem);
        }
        Stopwatch watch = new Stopwatch();
        watch.Start();
        ac();
        watch.Stop();
        Debug.Log(watch.ElapsedMilliseconds);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            Sort(() =>
            {
                SelectSort(_oldInts);
            });



        }
        if (Input.GetKeyDown(KeyCode.B))
        {
            Sort(() =>
            {
                BubleSort(_oldInts);
            });

        }
        if (Input.GetKeyDown(KeyCode.C))
        {
            Sort(() =>
            {
                InsertSort(_oldInts);
            });

        }
        if (Input.GetKeyDown(KeyCode.D))
        {
            Sort(() =>
            {
                ShellSort(_oldInts);
            });

        }
        if (Input.GetKeyDown(KeyCode.O))
        {
            Sort(() => { QuickSort(_oldInts, 0, _oldInts.Count - 1); });

        }
        if (Input.GetKeyDown(KeyCode.P))
        {
            Sort(() => { sort(_oldInts); });

        }
        if (Input.GetKeyDown(KeyCode.M))
        {
            ShowOldLists();
        }

    }
    /// <summary>
    /// 选择排序,每次循环把后面未排序完的元素中找到最小的放在数组后面
    /// </summary>
    /// <param name="lists"></param>
    private void SelectSort(List<int> lists)
    {
        for (int i = 0; i < lists.Count - 1; i++)
        {
            for (int j = i + 1; j < lists.Count; j++)
            {
                if (lists[i] > lists[j])
                {
                    int temValue = lists[i];
                    lists[i] = lists[j];
                    lists[j] = temValue;
                }
            }
        }

        OutputLists(lists);
    }
    /// <summary>
    /// 冒泡排序,每次把最小的一个放在最前面,依次到最后一个
    /// </summary>
    /// <param name="lists"></param>
    private void BubleSort(List<int> lists)
    {
        for (int i = 0; i < lists.Count; i++)
        {
            for (int j = lists.Count - 1; j > i; j--)
            {
                if (lists[j] < lists[j - 1])
                {
                    int temValue = lists[j - 1];
                    lists[j - 1] = lists[j];
                    lists[j] = temValue;
                }
            }
        }
        OutputLists(lists);
    }
    /// <summary>
    /// 插入排序,每次把下一个元素,插入到已经排好顺序的数组中
    /// </summary>
    /// <param name="lists"></param>
    private void InsertSort(List<int> lists)
    {
        for (int i = 0; i < lists.Count; i++)
        {
            for (int j = i; j > 0; j--)
            {
                if (lists[j] > lists[j - 1])
                {
                    break;
                }
                else
                {
                    int tem = lists[j];
                    lists[j] = lists[j - 1];
                    lists[j - 1] = tem;
                }
            }
        }

        OutputLists(lists);
    }
    /// <summary>
    /// 希尔排序,也叫缩小增量排序
    /// </summary>
    /// <param name="list"></param>
    private void ShellSort(List<int> list)
    {
        int step = list.Count / 2;
        bool change = false;
        while (step >= 1)
        {
            do
            {
                change = false;
                for (int i = 0; i < list.Count - step; i++)
                {


                    if (list[i] > list[i + step])
                    {
                        int tem = list[i + step];
                        list[i + step] = list[i];
                        list[i] = tem;
                        change = true;
                    }


                }
            } while (change);

            step = step / 2;
        }
        OutputLists(list);
    }

    private void OutputLists(List<int> lists)
    {
        //for (int i = 0; i < lists.Count; i++)
        //{
        //    Debug.Log(lists[i]+"\n");
        //}
    }

   
    
        public static void sort(List<int> arr)
        {
            //1.构建大顶堆
            for (int i = arr.Count / 2 - 1; i >= 0; i--)
            {
                //从第一个非叶子结点从下至上,从右至左调整结构
                adjustHeap(arr, i, arr.Count);
            }
            //2.调整堆结构+交换堆顶元素与末尾元素
            for (int j = arr.Count - 1; j > 0; j--)
            {
                swap(arr, 0, j);//将堆顶元素与末尾元素进行交换
                adjustHeap(arr, 0, j);//重新对堆进行调整
            }

        }

        /**
         * 调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上)
         * @param arr
         * @param i
         * @param length
         */
        public static void adjustHeap(List<int> arr, int i, int length)
        {
            int temp = arr[i];//先取出当前元素i
            for (int k = i * 2 + 1; k < length; k = k * 2 + 1)
            {//从i结点的左子结点开始,也就是2i+1处开始
                if (k + 1 < length && arr[k] < arr[k + 1])
                {//如果左子结点小于右子结点,k指向右子结点
                    k++;
                }
                if (arr[k] > temp)
                {//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
                    arr[i] = arr[k];
                    i = k;
                }
                else
                {
                    break;
                }
            }
            arr[i] = temp;//将temp值放到最终的位置
        }

        /**
         * 交换元素
         * @param arr
         * @param a
         * @param b
         */
        public static void swap(List<int> arr, int a, int b)
        {
            int temp = arr[a];
            arr[a] = arr[b];
            arr[b] = temp;
        }
    
    private void QuickSort(List<int> lists, int left, int right)
    {
        if (left >= right)
            return;
        int key = lists[left];
        int i = left;
        int j = right;

        while (i < j)
        {
            while (i < j && lists[j] >= key)
            {
                j--;
            }
            lists[i] = lists[j];
            while (i < j && lists[i] <= key)
            {
                i++;
            }
            lists[j] = lists[i];
        }

        lists[i] = key;
        QuickSort(lists, left, i - 1);
        QuickSort(lists, i + 1, right);


    }
    private void ShowOldLists()
    {
        OutputLists(_oldInts);
    }
}

这是四种排序方式打印出来的时间消耗:

快速排序和希尔排序的时间消耗要远小于其他几种排序,至于那个时间复杂度,抱歉,大学逃课去了,真心忘了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值