实例365(14)---------经典数组排序方法------快速排序法

一:截图

二:快速排序详解

快速排序法(QuickSort)是一种非常快的对比排序方法。它也Divide-And-Conquer思想的实现之一。自从其产生以来,快速排序理论得到了极大的改进,然而在实际中却十分难以编程出正确健壮的代码。本文将对快速排序算法的基本理论和编程实践方面做作一个全面的讲解。在本文讲解中,将忽略很多细枝末节,试图给读者形成一个非常具体的快速排序形象。

快速排序---基本理论

因为该算法是Divide-And-Conquer思想的一个实现,所以本文将以Divide-And-Conquer思想对其进行分析。首先,假设所要排序的数字存储在数组S中,则该算法的操作可以拆分为两部分:

  • 在S中选出一个元素v;
  • 将S数组分为三个子数组。其中v这个元素单独形成子数组1,比v小的元素形成子数组2,比v大的元素形成自数组3.
  • 分别对子数组2和子数组3进行前两步操作,实现递归排序;
  • 返回时,依次返回S1,V,S2;

该程序具有平均运行时间T(n) = O(nlgn), 最差运行时间T(n) = O(n^2);

下面给出一个简单的排序实例对以上算法进行简单说明:

初始数组为--------------> S: 6,10,13,5,8,3,2,11

将第一个元素赋值给v----->v = 6;

以v为标准将S进行拆分--->[2,5,3],[6],[8,13,10,11] <----------将得到的数组命名为S1, S2;

同样对子数组S1进行拆分->[ ], [2], [ 5, 3] <--------------------拆分之后,第一个子数组为空。将得到的数组命名为S12;

对子数组S2进行拆分----->[ ], [8], [13, 10, 11]<---------------将得到的数组命名为S22;

此时的数组S为---------->2,5,3,6,8,13,10,11

对子数组S12进行拆分---->[3], [5],[ ];

对自数组S22进行拆分---->[10,11],[13],[]<--------------------将得到的数组命名为S221

此时的数组S为----------->2,3,5,6,8,10,11,13

对子数组S221进行拆分--->[ ], [11], [13]

对后得到的数组为-------->2,3,5,6,8,10,11,13;

三:代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace FastSort
{
    public partial class Frm_Main : Form
    {
        public Frm_Main()
        {
            InitializeComponent();
        }

        private int[] G_int_value;//定义数组字段

        private Random G_Random = new Random();//创建随机数对象

        //交换数据
        private void swap(ref int l, ref int r)
        {
            int temp;//临时值
            temp = l;//记录前一个值
            l = r;//记录后一个值
            r = temp;//前后交换数据
        }
        /// <summary>
        ///快速排序
        /// </summary>
        /// <param name="list">要排序的数组</param>
        /// <param name="low">数组的起始位置</param>
        /// <param name="high">数组的结束位置</param>
        private void Sort(int[] list, int low, int high)
        {
            int pivot;//临时变量,用来存储最大值
            int l, r;//分别用来记录遍历到的索引和最大索引
            int mid;//中间索引
            if (high <= low)//判断输入的值是否合法
                return;
            else if (high == low + 1)//判断两个索引是否相邻
            {
                if (list[low] > list[high])//判断前面的值是否大于后面的值
                    swap(ref list[low], ref list[high]);//交换前后索引的值
                return;
            }
            mid = (low + high) >> 1;//记录数组的中间索引,相当于(low + high)除以2
            pivot = list[mid];//初始化临时变量的值
            swap(ref list[low], ref list[mid]);//交换第一个值和中间值的索引顺序
            l = low + 1;//记录遍历到的索引值
            r = high;//记录最大索引
            try
            {
                //使用do...while循环遍历数组,并比较前后值的大小
                do
                {

                    while (l <= r && list[l] < pivot)//判断遍历到的索引是否小于最大索引
                        l++;//索引值加1
                    while (list[r] >= pivot)//判断最大值是否大于等于记录的分支点
                        r--;//做大索引值减1
                    if (l < r)//如果当前遍历到的值小于最大值
                        swap(ref list[l], ref list[r]);//交换顺序

                } while (l < r);
                list[low] = list[r];//在最小索引处记录最小值
                list[r] = pivot;//在最大索引处记录最大值
                if (low + 1 < r)//判断最小索引是否小于最大索引
                    Sort(list, low, r - 1);//调用自身进行快速排序
                if (r + 1 < high)//判断最大索引是否小于数组长度
                    Sort(list, r + 1, high);//调用自身进行快速排序
            }
            catch { }
        }

        private void btn_sort_Click(object sender, EventArgs e)
        {
            if (G_int_value != null)
            {
                Sort(G_int_value, 0, G_int_value.Length-1);//使用快速排序法对数组进行排序
                txt_str2.Clear();//清空控件内字符串
                foreach (int i in G_int_value)//遍历字符串集合
                {
                    txt_str2.Text += i.ToString() + ", ";//向控件内添加字符串
                }
            }
            else
            {
                MessageBox.Show("首先应当生成数组,然后再进行排序。", "提示!");
            }
        }

        private void btn_Generate_Click(object sender, EventArgs e)
        {
            G_int_value = new int[G_Random.Next(10, 20)];//生成随机长度数组
            for (int i = 0; i < G_int_value.Length; i++)//遍历数组
            {
                G_int_value[i] = G_Random.Next(0, 100);//为数组赋随机数值
            }
            txt_str.Clear();//清空控件内字符串
            foreach (int i in G_int_value)//遍历字符串集合
            {
                txt_str.Text += i.ToString() + ", ";//向控件内添加字符串

            }
        }
    }
}

实例365(14)---------经典数组排序方法------快速排序法

时间: 2024-10-10 00:03:57

实例365(14)---------经典数组排序方法------快速排序法的相关文章

实例365(13)---------经典数组排序方法------选择排序法

一:使用选择排序法对一维数组进行排序,截图 /*选择排序的个人理解:第一遍筛选,选出其中最大的值,得到值和下标 将最大的值的位置和数组的第一个位置交换 从数组的第二个位置开始第二遍筛选 将其中最大的值的位置和数组的第二个位置交换 直到筛选完数组 */ 二:代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; u

实例365(15)--------------经典排序----插入排序法

前言:此代码设计的比较简洁,可能不太容易理解,插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕. 一:截图 二:代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.

实例365(13)---------经典数组排序方法------选择排序法,冒泡排序法

position:static(静态定位) 当position属性定义为static时,可以将元素定义为静态位置,所谓静态位置就是各个元素在HTML文档流中应有的位置 podisition定位问题.所以当没有定义position属性时,并不说明该元素没有自己的位置,它会遵循默认显示为静态位置,在静态定位状态下无法通过坐标值(top,left,right,bottom)来改变它的位置. position:absolute(绝对定位) 当position属性定义为absolute时,元素会脱离文档流

实例365(6)---------DateTime.ToString格式化日期,使用DateDiff方法获取日期时间的间隔数

一:DateTime.ToString格式化日期,截图 二:代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace TmrFormat { public part

实例365(7)---------使用DateAdd方法向指定日期添加一段时间间隔,使用TimeSpan对象获取时间间隔

一:使用DateAdd方法向指定日期添加一段时间间隔,截图 二:代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using Microsoft.VisualBasic; na

实例365(8)---------三种方法将字符串格式化为日期

一:DateTime.ParseExact方式,截图 二:代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace ConvertToString { public

实例365(5)---------DateTime.IsLeapYear 方法判断是否是闰年,DaysInMonth判断一个月有几天,Addday取得前一天的日期GetYesterDay

一:DateTime.IsLeapYear 方法判断是否是闰年,截图 二:代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace GetDays { public

快速排序法(一)

说明快速排序法(quick sort)是目前所公认最快的排序方法之一(视解题的对象而定),虽然快速排序法在最差状况下可以达O(n2),但是在多数的情况下,快速排序法的效率表现是相当不错的.快速排序法的基本精神是在数列中找出适当的轴心,然后将数列一分为二,分别对左边与右边数列进行排序,而影响快速排序法效率的正是轴心的选择.这边所介绍的第一个快速排序法版本,是在多数的教科书上所提及的版本,因为它最容易理解,也最符合轴心分割与左右进行排序的概念,适合对初学者进行讲解.解法这边所介绍的快速演算如下:将最

php排序介绍_冒泡排序_选择排序法_插入排序法_快速排序法

这里我们介绍一些常用的排序方法,排序是一个程序员的基本功,所谓排序就是对一组数据,按照某个顺序排列的过程. 充效率看 冒泡排序法<选择排序法<插入排序法 排序分两大类: 内部排序法 交换式排序法 冒泡法 基本思想: 冒泡排序法 案例: 1234567891011121314151617181920212223242526 //简单的$arr=array(0,5,-1); //现在我们把函数毛片封装成函数,利用以后使用//数组默认传递的是值,不是地址,&是地址符function bubb