經典數組排序方法------快速排序法


一:截圖

二:快速排序詳解

快速排序法(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() + ", ";//向控件內添加字符串

            }
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM