排序是咱們生活中常常會面對的問題。同窗們作操時會按照從矮到高排列;老師查看上課出勤狀況時,會按學生學號順序點名;高考錄取時,會按成績總分降序依次錄取等。排序是數據處理中常常使用的一種重要的運算,它在咱們的程序開發中承擔着很是重要的角色。算法
排序分爲如下四類共七種排序方法:數組
交換排序:dom
1) 冒泡排序
2) 快速排序ui
選擇排序:spa
3) 直接選擇排序
4) 堆排序pwa
插入排序:3d
5) 直接插入排序
6) 希爾排序code
合併排序:blog
7) 合併排序排序
這一篇文章主要總結的是交換排序,即冒泡排序和C#提供的快速排序。交換排序的基本思想是:兩兩比較待排序記錄的關鍵字,若是發現兩個記錄的次序相反時即進行交換,直到全部記錄都沒有反序時爲目上。本篇文章主要從如下幾個方面進行總結:
1,冒泡排序及算法實現
2,快速排序及算法實現
3,冒泡排序VS快速排序
什麼時冒泡排序呢?冒泡排序是一種簡單的排序方法,其基本思想是:經過相鄰元素之間的比較和交換,使關鍵字較小的元素逐漸從底部移向頂部,就像水底下的氣泡同樣逐漸向上冒泡,因此使用該方法的排序稱爲「冒泡」排序。
下面以一張圖來展現冒泡排序的全過程,其中方括號內爲下一躺要排序的區間,方括號前面的一個關鍵字爲本躺排序浮出來的最小關鍵字。
瞭解了冒泡排序的實現過程後,咱們很容易寫出冒泡排序的算法實現。
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; } } }
程序運行結果:
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#版
快速排序(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; } } } }
程序運行結果:
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(); }
關於冒泡排序和快速排序之間排序速度的比較我就選用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(); }
比較結果如圖:
可見,快速排序的速度比冒泡排序要快。