内部排序

2013-01-23

 摘要:内部排序,包括直接插入、冒泡、快速、简单选择,堆排序。

1 插入排序

 基本思想:将一个记录插入到以排好序的有序表中,从而得到一个新的、记录数增1的有序表。

1.1 直接插入排序

内部排序_第1张图片 

图1 直接插入排序

View Code
 1 public static void InsertSort(int[] arr)
 2         {
 3             int i, j;
 4             int temp;
 5             for (i = 1; i < arr.Length; i++)
 6             {
 7                 temp = arr[i];
 8                 for (j = i - 1; j >= 0 && temp < arr[j]; j--)
 9                 {
10                     arr[j + 1] = arr[j];
11                 }
12                 arr[j + 1] = temp;
13             }
14         }

2 快速排序

 快速排序时基于“交换”进行排序的方法。

2.1 冒泡排序

 基本思想:1)第一个和第二个比较,若逆序(First>Second),交换。然后进行第二个和第三个,以此类推,直到n-1和n个。这样,第一轮就把最大的“沉”到“底部”。

               2)然后,第二轮比较前n-1个就行,以此类推,得到有序表。

 内部排序_第2张图片

图2 冒泡排序

View Code
 1 //采用自上向下扫描
 2         public static void BubbleSort(int[] arr)
 3         {
 4             int i, j;
 5             int temp;
 6             for (i = arr.Length - 1; i > 0; i--)
 7             {
 8                 for (j = 0; j < i; j++) //对当前无序区R[0..n-i]自下向上扫描
 9                 {
10                     if (arr[j] > arr[j + 1])
11                     {
12                         temp = arr[j + 1];
13                         arr[j + 1] = arr[j];
14                         arr[j] = temp;
15                     }
16                 }
17             }
18         }

2.2 快速排序

 基本思想:1)通过一趟排序把待排记录分割成独立的两部分,前一部分都比某个记录效,后一部分都比某个记录大

      2)对前一部分和后一部分按1)再分区,直到整个序列有序。

内部排序_第3张图片

图3 快速排序

View Code
 1 public static void QuickSort(int[] arr)
 2         {
 3             QSort(arr, 0, arr.Length - 1);
 4         }
 5 
 6         public static void QSort(int[] arr, int low, int high)
 7         {
 8             if (low < high)
 9             {
10                 int pivotLoc = Partition(arr, low, high);
11                 QSort(arr, low, pivotLoc - 1);
12                 QSort(arr, pivotLoc + 1, high);
13             }
14         }
15 
16         public static int Partition(int[] arr, int low, int high)
17         {
18             int pivot = arr[low];
19             while (low < high)
20             {
21                 while ((high > low) && arr[high] >= pivot) --high;
22                 arr[low] = arr[high];
23                 while ((low < high) && (arr[low] <= pivot)) ++low;
24                 arr[high] = arr[low];
25             }
26             arr[low] = pivot;
27             return low;
28         }

 

3 选择排序

基本思想:每一趟在最后的n-i+1(i=1,2,...,n-1)中取最小的记录作为有序表的第i个记录。

3.1 简单选择排序

 内部排序_第4张图片

图4 简单选择排序

View Code
 1 public static void SelectSort(int[] arr)
 2         {
 3             int i, j;
 4             int minLoc;
 5             int temp;
 6             for (i = 0; i <= arr.Length - 1; i++)
 7             {
 8                 minLoc = i;
 9 
10                 for (j = i + 1; j <= arr.Length - 1; j++)
11                     if (arr[j] < arr[minLoc]) minLoc = j;
12 
13                 if (minLoc != i)
14                 {
15                     temp = arr[i];
16                     arr[i] = arr[minLoc];
17                     arr[minLoc] = temp;
18                 }
19             }
20         }

 

3.2 堆排序

堆的定义

图5 堆的定义

我们可以吧这个序列看成一个二叉树,可得, 1)最大堆的根节点最大,2)上层总比下层大

 

View Code
 1 public static void HeapSort(MyArr arr)
 2         {
 3             int i; int r;
 4             for (i = arr.Length / 2; i > 0; --i)
 5             {  //把H.r[1...H.length]建成大顶堆
 6                 HeapAdjust(arr, i, arr.Length - 1);
 7             }
 8             for (i = arr.Length; i > 1; --i)
 9             {
10                 //将堆顶记录和当前未经排序子序列H.r[1..i]中最后一个记录相互交换
11                 r = arr[1]; arr[1] = arr[i]; arr[i] = r;
12                 HeapAdjust(arr, 1, i - 1);  //将H.r[1..i-1]重新调整为大顶堆
13             }
14         }
15 
16         //小的放在下层
17         public static void HeapAdjust(MyArr arr, int s, int m)
18         {
19             int rc = arr[s];
20             for (int j = 2 * s; j <= m; j = 2 * j)
21             {  //沿key较大的孩子结点向下筛选
22                 if (j < m && arr[j] < arr[j + 1]) ++j; //j为key较大的记录的下标
23                 if (rc >= arr[j]) break; //rc应插入在位置s上
24                 arr[s] = arr[j]; s = j;
25             }
26             arr[s] = rc;   //插入
27         }
28 
29         //因为以零开始的数组,对于堆栈不好操作,也容易误解,所以自定义数组,以1起始
30         public class MyArr
31         {
32             int[] arr;
33             public int this[int pos]
34             {
35                 get
36                 {
37                     return arr[pos - 1];
38                 }
39                 set
40                 {
41                     arr[pos - 1] = value;
42                 }
43             }
44             public int Length
45             {
46                 get
47                 {
48                     return arr.Length;
49                 }
50             }
51             public MyArr(int[] arr)
52             {
53                 this.arr = arr;
54             }
55         }

4 客户端 

View Code
 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             //1 直接插入排序
 6             int[] sample = new int[] { 53, 27, 36, 15, 69, 42 };
 7             DisplayArray("Original Sequence is: ", sample);
 8             Sort.InsertSort(sample);
 9             DisplayArray("InsertSort Sequence is: ", sample);
10             //2 冒泡排序
11             sample = new int[] { 70, 30, 40, 10, 80, 20, 90, 100, 75, 60, 45 };
12             DisplayArray("Original Sequence is: ", sample);
13             Sort.BubbleSort(sample);
14             DisplayArray("BubbleSort Sequence is: ", sample);
15             //3 快速排序
16             sample = new int[] { 49, 38, 65, 97, 76, 13, 27 };
17             DisplayArray("Original Sequence is: ", sample);
18             Sort.QuickSort(sample);
19             DisplayArray("QuickSort Sequence is: ", sample);
20             //4 简单选择排序
21             sample = new int[] { 58, 23, 35, 10, 76, 12 };
22             DisplayArray("Original Sequence is: ", sample);
23             Sort.SelectSort(sample);
24             DisplayArray("SelectSort Sequence is: ", sample);
25             //5 堆排序
26             Sort.MyArr arr = new Sort.MyArr(new int[] { 49, 38, 65, 97, 76, 13, 27, 49 });
27             Console.Write("Original Sequence is: ");
28             for(int m=1;m<arr.Length;m++)
29                 Console.Write("{0}  ", arr[m].ToString());
30             Sort.HeapSort(arr);
31             Console.WriteLine();
32             Console.Write("HeapSort Sequence is: ");
33             for (int m = 1; m < arr.Length; m++)
34                 Console.Write("{0}  ", arr[m].ToString());
35 
36             Console.Read();
37         }
38 
39         public static void DisplayArray(string declare, int[] arr)
40         {
41             Console.Write(declare);
42             for (int m = 0; m < arr.Length; m++)
43                 Console.Write("{0}  ", arr[m].ToString());
44             Console.WriteLine();
45         }
46     }

 

5 各种内部排序比较

排序方法 平均情况  最坏情况  辅助空间 
直接插入排序 O(n2) O(n2) O(1)
起泡排序  O(n2) O(n2) O(1)
快速排序 O(nlogn)  O(n2) O(logn) 
简单选择排序  O(n2)  O(n2) O(1)
堆排序 O(nlogn)  O(nlogn)  O(1)

你可能感兴趣的:(排序)