C#版 选择法、冒泡法、插入法和快速排序法分析与对比(一)


前言

        之前老师就讲过了选择法和冒泡法,之后又提到了插入法和排序法,今天做了一个小DEMO,对比了一下四种方法的效率,当然看了很多大牛也博客,其实算法还设计了时间复杂度和空间复杂度,对于这两个概念,我只能从表面上进行理解,其中涉及到了很多数学的问题,所以就不展开写了。


选择排序

C#版 选择法、冒泡法、插入法和快速排序法分析与对比(一)_第1张图片

冒泡法

C#版 选择法、冒泡法、插入法和快速排序法分析与对比(一)_第2张图片

插入法

C#版 选择法、冒泡法、插入法和快速排序法分析与对比(一)_第3张图片

快速排序法

 这部分知识比较新,而且内容比较多,所以打算单独另外总结一遍博客,来详细的总结一下这个方法~


DEMO(比较三个算法所用时间)

     先说一下设计的思路,生成要求个数的不重复的随机数,将随机数循环赋给listbox,然后分别用四种方法对随机数进行排序,最后将排序时间显示到textbox中

窗体

C#版 选择法、冒泡法、插入法和快速排序法分析与对比(一)_第4张图片

关键代码

1.按照textbox中的要求生成随机数

其实这块的代码还没来得及好好研究,下次博客和快速排序一起总结一下吧~
<span style="font-size: 24px;">     </span><span style="font-size:14px;">private List<int> a = new List<int>();
        private HashSet<int> hs = new HashSet<int>();

        /// <summary>
        /// 生成随机数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnGenerate_Click(object sender, EventArgs e)
        {
            for (int i = listBox1.Items.Count - 1; i >= 0; i--)
            {
                listBox1.Items.RemoveAt(i);
            }
            //清空HashSet
            hs.Clear();

            int count = 0;
            try   //获取生成个数
            {
                count = Int32.Parse(txtCount.Text);
            }
            catch (Exception ex)
            {
                MessageBox.Show("个数有误");
            }
            Random r = new Random((int)DateTime.Now.Ticks); //以当前时间为时间随机种子

            //生成随机数
            for (int i = 0; hs.Count < count; i++)
            {
                hs.Add(r.Next(10000));//最多可以生成9999个数
            }
            a = hs.ToList<int>(); //HashSet转为List
            //a.Sort(); // 排序
            //输出随机数到列表
            for (int i = 0; i < a.Count; i++)
            {
                this.listBox1.Items.Add(a[i]);
            }
        }</span>

2.插入法

<span style="font-size:14px;">/// <summary>
        /// 插入法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            //哈希表转整数数组
            int[] s = hs.ToArray();
            DateTime time1 = DateTime.Now; 
            int count = Int32.Parse(txtCount.Text);

            for (int i = 1; i < count ; i++)  //外层循环,控制执行(n-1)趟排序
            {

                if (s[i] > s[i - 1])   //判断大小,决定是否需要交换
                {
                    int temp = s[i];     //如果需要交换,则将待排序记录放入临时变量中
                    int j = 0;
                    for (j = i - 1; j >= 0 && temp > s[j]; j--) //内层循环,在有序序列中从后往前比较,找到待排序记录在有序列中位置(位置空出)
                    {
                        s[j + 1] = s[j];    //将有序记录往后移
                    }
                    s[j + 1] = temp;  //将临时变量中的值放入正确位置,即空出的位置
                }
            }
            DateTime time2 = DateTime.Now;
            textBox3.Text = DateDiff(time1, time2);

            for (int i = listBox1.Items.Count - 1; i >= 0; i--)
            {
                listBox1.Items.RemoveAt(i);
            }
            for (int i = 0; i < s.Length; i++)
            {

                this.listBox1.Items.Add(s[i]);
            }
        }</span>


3.快速选择法

<span style="font-size:14px;"> /// <summary>
        /// 快速排序法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            //哈希表转整数数组
            int[] s = hs.ToArray();
            DateTime time1 = DateTime.Now;

            int low=0;                 //记录目标数组的起始位置
            int high=s.Length-1;   //记录目标数组的结束位置

            QuickSortFunction(s, low, high);

            DateTime time2 = DateTime.Now;
            textBox4.Text = DateDiff(time1, time2);

            for (int i = listBox1.Items.Count - 1; i >= 0; i--)
            {
                listBox1.Items.RemoveAt(i);
            }
            for (int i = 0; i < s.Length; i++)
            {

                this.listBox1.Items.Add(s[i]);
            }
        }


         /// <summary>
         /// 快速排序过程
         /// </summary>
         /// <param name="array">数组</param>
         /// <param name="low">低位目标数组下标</param>
         /// <param name="high">高位目标数组下边</param>
        private static void QuickSortFunction(int[] array, int low, int high)
         {
                 int keyValuePosition;   //记录关键值的下标
 
                 //当传递的目标数组含有两个以上的元素时,进行递归调用。(即:当传递的目标数组只含有一个元素时,此趟排序结束)
                 if (low < high) 
                 {
                     keyValuePosition = keyValuePositionFunction(array, low, high);  //获取关键值的下标(快排的核心)
 
                     QuickSortFunction(array, low, keyValuePosition - 1);    //递归调用,快排划分出来的左区间
                     QuickSortFunction(array, keyValuePosition + 1, high);   //递归调用,快排划分出来的右区间
                 }
         }

        /// <summary>
        /// 找出关键值位置
        /// </summary>
        /// <param name="array">数组</param>
        /// <param name="low">低位下标</param>
        /// <param name="high">高位下标</param>
        /// <returns>关键值下标</returns>
        private static int keyValuePositionFunction(int[] array, int low, int high)
         {
             int i = low;        //记录目标数组的起始位置(后续动态的左侧下标)
             int j = high;      //记录目标数组的结束位置(后续动态的右侧下标)
 
             int keyValue = array[low];  //数组的第一个元素作为关键值
             int temp;
 
             //当 (左侧动态下标 == 右侧动态下标) 时跳出循环
             while (i< j)
             {
                 while (i < j && array[j] > keyValue)  //必须先从右边开始,逐渐向左移动,直至找到<=keyValue的下标
                 {
                     j--;
                 }
                 while (i < j && array[j] <= keyValue)  //从左边开始,直至找到>=keyValue的下标
                 {
                     i++;
                 }
                 if(i < j)  //如果leftIndex < rightIndex,则交换左右动态下标所指定的值;当leftIndex==rightIndex时,跳出整个循环
                 {
                     temp = array[i];
                     array[i] = array[j];
                     array[j] = temp;
                 }
             }
 
             //当左右两个动态下标相等时(即:左右下标指向同一个位置),此时便可以确定keyValue的准确位置
             temp = keyValue;
             if (temp < array[j])   //当keyValue < 左右下标同时指向的值,将keyValue与rightIndex - 1指向的值交换,并返回rightIndex - 1
             {
                 array[low] = array[j - 1];
                 array[j - 1] = temp;
                 return j - 1;
             }
             else //当keyValue >= 左右下标同时指向的值,将keyValue与rightIndex指向的值交换,并返回rightIndex
             {
                 array[low] = array[j];
                 array[j] = temp;
                 return j;
             }
         }</span>


写在后边的碎碎念

总结这四个算法,花了一天的时间,虽然画图的时候也会嫌麻烦,但是画过之后,印象真的深刻了,知道自己哪里不懂,哪里还需要补充学习,最开始选择法和排序法是在学习C语言的课上,那会真的觉得没意思,但是现在自己静下心来自学了插入法和快速排序法之后,觉得算法真的是一门艺术,一大堆的数在等着你来给他们排排队,有一种世界被我掌控的感觉,说的有些夸张,但是学习中的乐趣只有学进去了才能体会吧,不过我可不是书呆子,真正研究数学的大家也都没有学傻,不管怎样,在心里重新定义了算法,给大家推荐一本书《啊哈!算法!》,通俗易懂,妙趣横生!快速排序就是跟啊哈磊学的,下边是链接,不谢,叫我雷锋好吗~


点我:

https://yunpan.cn/cPD8d8L2tTqeK  访问密码 08d7



你可能感兴趣的:(C#版 选择法、冒泡法、插入法和快速排序法分析与对比(一))