數據結構和算法系列5 七大排序之冒泡排序和快速排序

排序是咱們生活中常常會面對的問題。同窗們作操時會按照從矮到高排列;老師查看上課出勤狀況時,會按學生學號順序點名;高考錄取時,會按成績總分降序依次錄取等。排序是數據處理中常常使用的一種重要的運算,它在咱們的程序開發中承擔着很是重要的角色。算法

排序分爲如下四類共七種排序方法:數組

交換排序:dom

1) 冒泡排序
2) 快速排序ui

選擇排序:spa

3) 直接選擇排序
4) 堆排序pwa

插入排序:3d

5) 直接插入排序
6) 希爾排序code

合併排序:blog

7) 合併排序排序

這一篇文章主要總結的是交換排序,即冒泡排序和C#提供的快速排序。交換排序的基本思想是:兩兩比較待排序記錄的關鍵字,若是發現兩個記錄的次序相反時即進行交換,直到全部記錄都沒有反序時爲目上。本篇文章主要從如下幾個方面進行總結:

1,冒泡排序及算法實現

2,快速排序及算法實現

3,冒泡排序VS快速排序

1,冒泡排序及算法實現

什麼時冒泡排序呢?冒泡排序是一種簡單的排序方法,其基本思想是:經過相鄰元素之間的比較和交換,使關鍵字較小的元素逐漸從底部移向頂部,就像水底下的氣泡同樣逐漸向上冒泡,因此使用該方法的排序稱爲「冒泡」排序。

下面以一張圖來展現冒泡排序的全過程,其中方括號內爲下一躺要排序的區間,方括號前面的一個關鍵字爲本躺排序浮出來的最小關鍵字。

ds19

瞭解了冒泡排序的實現過程後,咱們很容易寫出冒泡排序的算法實現。

C#版:

namespace BubbleSort.CSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> list = new List<int>() { 50, 10, 90, 30, 70, 40, 80, 60, 20 };
            Console.WriteLine("********************冒泡排序********************");
            Console.WriteLine("排序前:");
            Display(list);

            Console.WriteLine("排序後:");
            BubbleSort(list);
            Display(list);

            Console.ReadKey();
        }

        /// <summary>
        /// 打印結果
        /// </summary>
        /// <param name="list"></param>
        private static void Display(List<int> list)
        {
            Console.WriteLine("\n**********展現結果**********\n");

            if (list!=null&&list.Count>0)
            {
                foreach (var item in list)
                {
                    Console.Write("{0} ", item);
                }
            }
            
            Console.WriteLine("\n**********展現完畢**********\n");
        }

        /// <summary>
        /// 冒泡排序算法
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        private static List<int> BubbleSort(List<int> list)
        {
            int temp;
            //作多少躺排序(最多作n-1躺排序)
            for (int i = 0; i < list.Count-1; i++)
            {
                //從後往前循環比較(注意j的範圍)
                for (int j = list.Count - 1; j > i; j--)
                {
                    if (list[j - 1] > list[j])
                    { 
                        //交換次序
                        temp=list[j-1];
                        list[j-1]=list[j];
                        list[j] = temp;
                    }
                }
            }
            return list;
        }
    }
}

程序運行結果:

ds20

 

C語言版:

/*包含頭文件*/
#include "stdio.h"
#include "stdlib.h"   
#include "io.h"
#include "math.h" 
#include "time.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
/* 用於快速排序時判斷是否選用插入排序闕值 */
#define MAX_LENGTH_INSERT_SORT 7
/* 用於要排序數組個數最大值,可根據須要修改 */
#define MAXSIZE 100

typedef int Status; 
typedef struct
{
    int data[MAXSIZE];
    int length;    
}SeqList;

/*冒泡排序算法*/
void BubbleSort(SeqList *seqList)
{
    int i,j;

    //作多少躺排序(最多作n-1躺排序)
    for (i=0;i<seqList->length-1;i++)
    {
        //從後往前循環比較(注意j的範圍)
        for (j=seqList->length-1;j>i;j--)
        {
            if (seqList->data[j-1]>seqList->data[j])
            {
                //交換次序
                int temp=seqList->data[j-1];
                seqList->data[j-1]=seqList->data[j];
                seqList->data[j]=temp;
            }
        }
    }
}

/*打印結果*/
void Display(SeqList *seqList)
{
    int i;
    printf("\n**********展現結果**********\n");

    for (i=0;i<seqList->length;i++)
    {
        printf("%d ",seqList->data[i]);
    }

    printf("\n**********展現完畢**********\n");
}

#define N 9
void main()
{
    int i,j;
    SeqList seqList;

    //定義數組
    int d[N]={50,10,90,30,70,40,80,60,20};

    for (i=0;i<N;i++)
    {
        seqList.data[i]=d[i];
    }
    seqList.length=N;

    printf("***************冒泡排序***************\n");
    printf("排序前:");
    Display(&seqList);

    BubbleSort(&seqList);
    printf("\n排序後:");
    Display(&seqList);

    getchar();
}

程序運行結果同C#版

2,快速排序及算法實現

快速排序(Quick Sort)又稱爲劃分交換排序。快速排序是對冒泡排序的一種改進方法,在冒泡排序中,進行記錄關鍵字的比較和交換是在相鄰記錄之間進行的,記錄每次交換隻能上移或下移一個相鄰位置,於是總的比較和移動次數較多,效率相對較低。而在快速排序中,記錄關鍵字的比較和記錄的交換是從兩端向中間進行的,待排序關鍵字較大的記錄一次就可以交換到後面單元中,而關鍵字較小的記錄一次就能交換到前面單元中,記錄每次移動的距離較遠,所以總的比較和移動次數較少,速度較快,故稱爲「快速排序」。

快速排序的基本思想是:經過一躺排序將待排記錄分割成獨立的兩部分, 其中一部分記錄的關鍵字均比另外一部分記錄的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序的目的。

下面是實現代碼:

C#版:

namespace QuickSort.CSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> list = new List<int> { 50, 10, 90, 30, 70, 40, 80, 60, 20 };
            Console.WriteLine("********************快速排序********************");
            Console.WriteLine("排序前:");
            Display(list);

            Console.WriteLine("排序後:");
            QuickSort(list,0,list.Count-1);
            Display(list);

            Console.ReadKey();
        }

        /// <summary>
        /// 打印列表元素
        /// </summary>
        /// <param name="list"></param>
        private static void Display(List<int> list)
        {
            Console.WriteLine("\n**********展現結果**********\n");

            if (list != null && list.Count > 0)
            {
                foreach (var item in list)
                {
                    Console.Write("{0} ", item);
                }
            }

            Console.WriteLine("\n**********展現完畢**********\n");
        }

        /// <summary>
        /// 快速排序算法
        /// </summary>
        /// <param name="list"></param>
        /// <param name="low"></param>
        /// <param name="high"></param>
        public static void QuickSort(List<int> list, int low, int high)
        {
            if (low < high)
            {
                //分割數組,找到樞軸
                int pivot = Partition(list,low,high);

                //遞歸調用,對低子表進行排序
                QuickSort(list,low,pivot-1);
                //對高子表進行排序
                QuickSort(list,pivot+1,high);
            }
        }

        /// <summary>
        /// 分割列表,找到樞軸
        /// </summary>
        /// <param name="list"></param>
        /// <param name="low"></param>
        /// <param name="high"></param>
        /// <returns></returns>
        private static int Partition(List<int> list, int low, int high)
        {
            //用列表的第一個記錄做樞軸記錄
            int pivotKey = list[low];

            while (low < high)
            {
                while (low < high && list[high] >= pivotKey)
                    high--;
                Swap(list,low,high);//交換

                while (low < high && list[low] <= pivotKey)
                    low++;
                Swap(list,low,high);
            }
            //返回樞軸所在位置
            return low;
        }

        /// <summary>
        /// 交換列表中兩個位置的元素
        /// </summary>
        /// <param name="list"></param>
        /// <param name="low"></param>
        /// <param name="high"></param>
        /// <returns></returns>
        private static void Swap(List<int> list, int low, int high)
        {
            int temp = -1;
            if (list != null && list.Count > 0)
            {
                temp = list[low];
                list[low] = list[high];
                list[high] = temp;
            }
        }
    }
}

程序運行結果:

ds21

 

C語言版:

/*包含頭文件*/
#include <stdio.h>    
#include <string.h>
#include <ctype.h>      
#include <stdlib.h>   
#include <io.h>  
#include <math.h>  
#include <time.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
/* 用於快速排序時判斷是否選用插入排序闕值 */
#define MAX_LENGTH_INSERT_SORT 7
/* 用於要排序數組個數最大值,可根據須要修改 */
#define MAXSIZE 100

typedef int Status; 
typedef struct
{
    int data[MAXSIZE];
    int length;    
}SeqList;

/*快速排序算法*/
void QuickSort(SeqList *seqList,int low,int high)
{
    int pivot;
    while(low<high)
    {
        //分割列表,找到樞軸
        pivot=Partition(seqList,low,high);

        //遞歸調用,對低子列表進行排序
        QuickSort(seqList,low,pivot-1);
        QuickSort(seqList,pivot+1,high);
    }
}

/*交換順序表L中子表的記錄,使樞軸記錄到位,並返回其所在位置*/
/* 此時在它以前(後)的記錄均不大(小)於它。 */
int Partition(SeqList *seqList,int low,int high)
{
    int pivotkey;
    pivotkey=seqList->data[low];

    /*  從表的兩端交替地向中間掃描 */
    while(low<high) 
    { 
        while(low<high&&seqList->data[high]>=pivotkey)
            high--;
        Swap(seqList,low,high);

        while(low<high&&seqList->data[low]<=pivotkey)
            low++;
        Swap(seqList,low,high);
    }
    return low;
}

/* 交換L中數組SeqList下標爲i和j的值 */
void Swap(SeqList *seqList,int i,int j)
{
    int temp;
    temp=seqList->data[i];
    seqList->data[i]=seqList->data[j];
    seqList->data[j]=temp;
}

/*打印結果*/
void Display(SeqList *seqList)
{
    int i;
    printf("\n**********展現結果**********\n");

    for (i=0;i<seqList->length;i++)
    {
        printf("%d ",seqList->data[i]);
    }

    printf("\n**********展現完畢**********\n");
}

#define N 9
void main()
{
    int i,j;
    SeqList seqList;

    //定義數組
    int d[N]={50,10,90,30,70,40,80,60,20};

    for (i=0;i<N;i++)
    {
        seqList.data[i]=d[i];
    }
    seqList.length=N;

    printf("***************快速排序***************\n");
    printf("排序前:");
    Display(&seqList);

    QuickSort(&seqList,0,seqList.length-1);
    printf("\n排序後:");
    Display(&seqList);

    getchar();
}
程序運行結果同上。

3,冒泡排序VS快速排序

關於冒泡排序和快速排序之間排序速度的比較我就選用C#語言版本的來進行,代碼以下:

static void Main(string[] args)
        {
            //共進行三次比較
            for (int i = 1; i <= 3; i++)
            { 
                //初始化List
                List<int> list = new List<int>();
                for (int j = 0; j < 1000; j++)
                {
                    Thread.Sleep(1);
                    list.Add(new Random((int)DateTime.Now.Ticks).Next(0,10000));
                }

                //快速排序(系統內置)耗費時間
                Console.WriteLine("\n第"+i+"次比較:");
                Stopwatch watch = new Stopwatch();
                watch.Start();
                var result = list.OrderBy(p => p).ToList();
                watch.Stop();
                Console.WriteLine("\n快速排序(系統)耗費時間:"+watch.ElapsedMilliseconds);
                Console.WriteLine("輸出前十個數:"+String.Join(",",result.Take(10).ToList()));

                //快速排序(自定義)耗費時間
                watch.Start();
                QuickSort.CSharp.Program.QuickSort(list,0,list.Count-1);
                watch.Stop();
                Console.WriteLine("\n快速排序(自定義)耗費時間:" + watch.ElapsedMilliseconds);
                Console.WriteLine("輸出前十個數:" + String.Join(",", result.Take(10).ToList()));

                //冒泡排序耗費時間
                watch.Start();
                result = BubbleSort(list);
                watch.Stop();
                Console.WriteLine("\n冒泡排序耗費時間:" + watch.ElapsedMilliseconds);
                Console.WriteLine("輸出前十個數:" + String.Join(",", result.Take(10).ToList()));
            }
            Console.ReadKey();
        }

比較結果如圖:

ds23

可見,快速排序的速度比冒泡排序要快。

相關文章
相關標籤/搜索