Unity学习之C#___排序算法(简单选择排序、插入排序、冒泡排序和快速排序)

排序是在编程过程中会经常遇到,并且十分重要,在了解排序算法前,先了解下排序的基本概念

排序项:作为排序依据的数据称为排序项,也称为记录的关键码(Keyword)

* 关键码(关键码分为两种)
* 主关键码 (Primary Keyword)  如果关键码是主关键码 排序结果是唯一的
* 次关键码(Secondary Keyword) 如果关键码是次关键码 则排序结果不唯一
判断排序方法是不是稳定排序方法

如果使用某个排序方法对任意的记录序列按关键码进行排序,相同的关键码值的记录之间的位置关系与排列前一致,则排序方法是稳定的;如果不一致,则排序方法是不稳定的。

例如下面的一队数据

主关键码就是 姓名的ASCALL码值,次关键码就是 分数
如果一个排序方法以次关键码(分数)进行从大到小排序,如果每一次排序结果的 a,b前后位置都没有发生改变,那么这个方式就是稳定方法,但是如果有一次a,b位置发生改变,那么这个方法就是不稳定方法,
Unity学习之C#___排序算法(简单选择排序、插入排序、冒泡排序和快速排序)_第1张图片
四种排序算法

一、直接插入排序(稳定排序方法)

这里我画了一个图有点抽象,看文字,辅助理解
Unity学习之C#___排序算法(简单选择排序、插入排序、冒泡排序和快速排序)_第2张图片
排序思路:从第二个元素开始遍历,让当前的元素(a)和前面的所有的元素(b)进行比较,如果前面的元素(b)大于当前元素(a)就把(b)向后移动一位下标,如果前面的元素(b)小于当前元素(a),那么就把当前元素(a)存储(b)下标+1的位置。遍历完后如果所有的(b)都大于当前元素(a)那么就把(a)存入第一个元素的位置。
代码

/// 
        /// 直接插入算法 稳定排序
        /// 
        /// 
        static void InsetSort(int[] array)
        {
            //首先从第二个元素开始遍历
            for (int i = 1; i < array.Length; i++)
            {
                int value = array[i];
                bool isMin = true;
                //让 i 下标前的全部数据和 i下标数据进行比较
                for (int j = i-1; j>=0 ; j--)
                {
                    if(array[j]>value)//只要比i下标数据大就向后移一位下标,
                    {
                        array[j + 1] = array[j];
                    }
                    else//如果比i下标数据小或者相等,那么就把i下标数据赋值到他后面
                    {
                        array[j+1] = value;
                        isMin = false;
                        break;//这里需要跳出循环,因为前面的值都是比i下标数据小
                    }
                }
                if(isMin)//如果遍历完了,前面的数据都比我大,那i下标数据就到第一个位置去
                {
                    array[0] = value;
                }
            }
        }  
二、简单选择排序 (不稳定排序算法)

排序思路:这个比较好理解,就是拿第一个元素和后面所有的元素进行比较,找出最小的然后交换位置,再拿第二元素和后面全
的元素进行比较,然后交换位置,一直遍历到长度-2个元素。
代码

/// 
        /// 简单选择排序  不稳定排序
        /// 
        /// 
        static void SelectSort(int[] array)
        {
            for (int j = 0; j < array.Length-1; j++)//遍历次数长度-1
            {
                int index = j;
                for (int i = j + 1; i < array.Length; i++)
                {
                    if (array[i] < array[index])//找到最小的
                    {
                        index = i;
                    }
                }
                //交换位置
                int temp = array[index];
                array[index] = array[j];
                array[j] = temp;
            }            
        }
三、冒泡排序(稳定排序算法)

Unity学习之C#___排序算法(简单选择排序、插入排序、冒泡排序和快速排序)_第3张图片
排序思路:冒泡排序的思路就是,让相邻的两数据进行比较,满足条件就进行位置交换,这样一轮遍历下来,最后一个数据一定是最大或者最小的,这样下一轮遍历就可以不用遍历最后一个数据,以此类推,遍历次数是数组长度-1
代码

/// 
        /// 冒泡排序  稳定排序
        /// 
        /// 
        static void BubbleSort(int[] array)
        {
            for (int i = 1; i < array.Length ; i++)//遍历数组长度-1的次
            {
                for (int j = 0; j < array.Length - i; j++)
                {
                    if (array[j] > array[j + 1])
                    {
						//位置交换                    
                        int temp = array[j + 1];
                        array[j + 1] = array[j];
                        array[j] = temp;
                    }
                }
            }            
        }
四、快速排序(不稳定排序算法)

这里放一张维基百科上快速排序的GIF图,一看就知道咋回事
Unity学习之C#___排序算法(简单选择排序、插入排序、冒泡排序和快速排序)_第4张图片
Unity学习之C#___排序算法(简单选择排序、插入排序、冒泡排序和快速排序)_第5张图片
排序思路:快速排序采用了一个分治的策略,在开始排序前,你需要先获得三个参数,i=0(i代表第一位索引);j=7(j代表最后一个位索引),x=[i]=89(x代表第一位索引的值)。拿到参数后,x 的作用是保存的 i 位置的元素,所以现在 i 位置等于是空出来了,于是我们开始操作,我们先从 j 开始向前遍历,如果发现比 x 大 那么 j–,如果发现比x小的数就把他存入 i 的位置,这时 j 的位置就空出来,我们在从 i 开始遍历,如果发现比 x 小,那么 i++,如果发比 x 大的数,就把他存入 j 的位置,此时 i 的位置就又空出来了,就这样一直循环直到 j==i 或者 j !> i 。就停止循环,然后我们在把 x 赋值到 i 或者 j 位置 。这样第一轮就做完了,我们等于是以 x=[i]=89 为中间值 把大于他的数放到了他的右边,小于他的数放到了左边。
第一轮完成后的数组的排序,你会发现,i=4左边的数都是小于89的,右边的数都是大于89的,但是这两边的数据排序确实不对的,所以这个时候我们就需要 递归调用,让89左边和右边的部分,再次调用一次本函数。
以上就是快速排序的思路,需要注意的事,快速排序的x可以是数组里面随便哪一个数,并不是固定的,这里用 i 索引的值是为了算法服务的。
Unity学习之C#___排序算法(简单选择排序、插入排序、冒泡排序和快速排序)_第6张图片
代码
这是我自己写的

 		/// 
        /// 快速排序 不稳定算法
        /// 
        /// 
        /// 开始索引
        /// 结束索引
        static void QuickSort(int[] array,int left,int right)
        {
            if(left x)
                        {
                            array[j] = array[i];
                            break;
                        }
                        else//如果小于等于,那么就把i向后移
                        {
                            i++;
                        }
                    }
                    //这时已经跳出两个小循环了,说明i==j了,
                    //这是再把 x 赋值给i/j位置
                    array[i] = x;                                        
                }
                //递归调用
                QuickSort(array, left, i - 1);
                QuickSort(array, j + 1, right);
            }           
        }

这是维基百科上展示的快速排序的代码,他这里的 x 值用的就不是 i 索引的值,而是中间索引的值

		/// 
        /// 快速排序2
        /// 
        /// 
        /// 
        /// 
        static void QuickSortPlus(int[] numbers, int left, int right)
        {
            if (left < right)
            {
                //因为他拿到的是中间索引的值,所以不需要随后一步赋值
                int middle = numbers[(left + right) / 2];
                int i = left - 1;
                int j = right + 1;
                while (true)
                {
                    while (numbers[++i] < middle) ;

                    while (numbers[--j] > middle) ;

                    if (i >= j)
                        break;

                    Swap(numbers, i, j);
                }

                QuickSortPlus(numbers, left, i - 1);
                QuickSortPlus(numbers, j + 1, right);
            }
        }
        
		//数据交换方法
        static void Swap(int[] numbers, int i, int j)
        {
            int number = numbers[i];
            numbers[i] = numbers[j];
            numbers[j] = number;
        }
以上就是全部四种的排序算法,从排序效率上来说,快速排序的效率是上面四种中较高的,并且快速排序的思路也和其他三种不太一样。

测试
这里我做了一个测试,给1000个数排序,看那种方法耗时最短。

static void Main(string[] args)
        {
            //排序算法测试
            int[] intArray = new int[] { 5, 16, 100, 1, 3, 50, 250, 23, 40, 21, 4, 15 };
            int[] arrays = new int[1000];
            //写入数据
            for (int i = 0; i <1000; i++)
            {
                arrays[i] = intArray[i % 10];
            }
            //打印
            foreach (int t in arrays)
            {
                Console.Write(t + " ");
            }
            Console.WriteLine();

            //开始排序
            DateTime beforSave = System.DateTime.Now;
            //InsetSort(arrays);            
            //SelectSort(arrays);
            //BubbleSort(arrays);          
            //QuickSort(arrays, 0, arrays.Length - 1);
            //QuickSortPlus(arrays, 0, arrays.Length - 1);
            DateTime afterSave = System.DateTime.Now;
            TimeSpan cost = afterSave.Subtract(beforSave);
            Console.WriteLine("排序花费时间 " + cost);
            Console.WriteLine();
            //打印结果
            foreach (int t in arrays)
            {
                Console.Write(t + " ");
            }

            Console.ReadKey();
        }

测试结果
1.直接插入排序
在这里插入图片描述
2.简单选择排序
在这里插入图片描述
3.冒泡排序
在这里插入图片描述
4.快速排序(自己的版本)
在这里插入图片描述
4.1快速排序(维基百科的版本)
在这里插入图片描述
上面的测试,可以自己试一下,不知到是不是1000个数太少了,多次的测试,结果出入还是比较大的
分享让知识变得有意义!后续会继续更新一些学习中问题。
OJMars
InTheMars

你可能感兴趣的:(unity学习)