zoukankan      html  css  js  c++  java
  • 排序

    一.归并排序

     1 #include<iostream>
     2 using namespace std;
     3 
     4 template<typename T>
     5 void Merge(T A[], int p, int q, int r)
     6 {
     7     int n1 = q - p + 1;
     8     int n2 = r - q;
     9 
    10     T *B = new T[n1];
    11     T *C = new T[n2];
    12 
    13     for (int i = p; i <= q; i++)
    14     {
    15         B[i - p] = A[i];
    16     }
    17     for (int i = q + 1; i <= r; i++)
    18     {
    19         C[i - q - 1] = A[i];
    20     }
    21 
    22     int m = 0, n = 0;
    23     for (int i = p; i <= r; i++)
    24     {
    25         if (m == n1 && n != n2)
    26         {
    27             while (n != n2)
    28             {
    29                 A[i] = C[n];
    30                 i++;
    31                 n++;
    32             }
    33             break;
    34         }
    35         if (m != n1 && n == n2)
    36         {
    37             while (m != n1)
    38             {
    39                 A[i] = B[m];
    40                 i++;
    41                 m++;
    42             }
    43             break;
    44         }
    45         if (B[m] <= C[n])
    46         {
    47             A[i] = B[m];
    48             m++;
    49         }
    50         else
    51         {
    52             A[i] = C[n];
    53             n++;
    54         }
    55     }
    56 }
    57 
    58 template<typename T>
    59 void MergeSort(T A[], int p, int r)
    60 {
    61     if (A != NULL && p >= 0 && r >= 0 && p < r)
    62     {
    63         int q = (p + r) / 2;
    64         MergeSort(A, p, q);
    65         MergeSort(A, q + 1, r);
    66         Merge(A, p, q, r);
    67     }
    68 }
    69 
    70 int main()
    71 {
    72     double A[] = { 1.1, -2.1, 3, 3, 4, -10, 4, 2.6 };
    73     MergeSort(A, 0, 7);
    74     for (int i = 0; i < 8; i++)
    75     {
    76         cout << A[i] << " ";
    77     }
    78     cout << endl;
    79     return 0;
    80 }

    归并排序最大的特色就是它是一种稳定的排序算法。归并过程中是不会改变元素的相对位置的。 缺点是,它需要O(n)的额外空间。但是很适合于多链表排序。

    适用于排序大列表,基于分治法。

    二.插入排序

     1 #include<iostream>
     2 using namespace std;
     3 
     4 template <typename T>
     5 void InsertionSort(T A[], int length)
     6 {
     7     if (A == NULL || length <= 0)
     8         return;
     9     for (int i = 1; i < length; i++)
    10     {
    11         T num = A[i];
    12         int j = i - 1;
    13         while (j >= 0 && num < A[j])
    14         {
    15             A[j + 1] = A[j];
    16             j--;
    17         }
    18         A[j + 1] = num;
    19     }
    20 }
    21 
    22 int main()
    23 {
    24     double A[] = { 1.1, -2.1, 3, 3, 4, -10, 4, 2.6 };
    25     InsertionSort(A, 8);
    26     for (int i = 0; i < 8; i++)
    27     {
    28         cout << A[i] << " ";
    29     }
    30     cout << endl;
    31     return 0;
    32 }

    稳定性,就是有两个相同的元素,排序先后的相对位置是否变化,主要用在排序时有多个排序规则的情况下。在插入排序中,K1是已排序部分中的元素,当K2和K1比较时,直接插到K1的后面(没有必要插到K1的前面,这样做还需要移动,因此,插入排序是稳定的。

    适用于排序小列表若列表基本有序,则插入排序比冒泡、选择更有效率。

    三.快速排序

     1 #include<iostream>
     2 using namespace std;
     3 
     4 template <typename T>
     5 int Partition(T A[], int p, int r)
     6 {
     7     T x = A[r];
     8     int i = p - 1;
     9     for (int j = p; j <= r - 1; j++)
    10     {
    11         if (A[j] <= x)
    12         {
    13             i++;
    14             T temp = A[j];
    15             A[j] = A[i];
    16             A[i] = temp;
    17         }
    18     }
    19     T temp = A[i + 1];
    20     A[i + 1] = A[r];
    21     A[r] = temp;
    22     return i + 1;
    23 }
    24 
    25 template <typename T>
    26 void QuickSort(T A[], int p, int r)
    27 {
    28     if (A != NULL && p >= 0 && r >= 0 && p < r)
    29     {
    30         int q = Partition(A, p, r);
    31         QuickSort(A, p, q - 1);
    32         QuickSort(A, q + 1, r);
    33     }
    34 }
    35 
    36 int main()
    37 {
    38     double A[] = { 1.1, -2.1, 3, 3, 4, -10, 4, 2.6 };
    39     QuickSort(A, 0, 7);
    40     for (int i = 0; i < 8; i++)
    41     {
    42         cout << A[i] << " ";
    43     }
    44     cout << endl;
    45     return 0;
    46 }

    由于每次都需要和中轴元素交换,因此原来的顺序就可能被打乱。如序列为 5 3 3 4 9 8 9 10 6 会将9的顺序打乱。所以说,快速排序是不稳定的!

    平均效率O(nlogn),适用于排序大列表。 
    此算法的总时间取决于枢纽值的位置;选择第一个元素作为枢纽,可能导致O(n²)的最糟用例效率。若数基本有序,效率反而最差。选项中间值作为枢纽,效率是O(nlogn)。 
    基于分治法。

    若要快排稳定,开额外O(n)空间.每轮partition都直接扫一遍p~r, 小于key的放一个数组,大于key的放另外一个数组. 然后再合并到原数组当中.这样就是稳定的了

    快排改进:

     1 #include<iostream>
     2 #include<stdlib.h>
     3 using namespace std;
     4 
     5 template <typename T>
     6 void InsertionSort(T A[], int p, int r)
     7 {
     8     for (int i = p + 1; i <= r; i++)
     9     {
    10         T key = A[i];
    11         int j = i - 1;
    12         while (j >= p && A[j] > key)
    13         {
    14             A[j + 1] = A[j];
    15             j--;
    16         }
    17         A[j + 1] = key;
    18     }
    19 }
    20 
    21 template <typename T>
    22 int Partition(T A[], int p, int r)
    23 {
    24     T x = A[r];
    25     int i = p - 1;
    26     for (int j = p; j <= r - 1; j++)
    27     {
    28         if (A[j] <= x)
    29         {
    30             i++;
    31             T temp = A[j];
    32             A[j] = A[i];
    33             A[i] = temp;
    34         }
    35     }
    36     T temp = A[i + 1];
    37     A[i + 1] = A[r];
    38     A[r] = temp;
    39     return i + 1;
    40 }
    41 
    42 template <typename T>
    43 int RandomizedPartition(T A[], int p, int r)
    44 {
    45     int i = rand() % (r - p + 1) + p;
    46     T temp = A[r];
    47     A[r] = A[i];
    48     A[i] = temp;
    49     return Partition(A, p, r);
    50 }
    51 
    52 template <typename T>
    53 void QuickSort(T A[], int p, int r)
    54 {
    55     if (A != NULL && p >= 0 && r >= 0)
    56     {
    57         if (r - p < 5)
    58         {
    59             InsertionSort(A, p, r);
    60         }
    61         else
    62         {
    63             int q = RandomizedPartition(A, p, r);
    64             QuickSort(A, p, q - 1);
    65             QuickSort(A, q + 1, r);
    66         }
    67     }
    68 }
    69 
    70 int main()
    71 {
    72     double A[] = { 1.1, -2.1, 3, 3, 4, -10, 4, 2.6 ,20, 10};
    73     QuickSort(A, 0, 9);
    74     for (int i = 0; i < 10; i++)
    75     {
    76         cout << A[i] << " ";
    77     }
    78     cout << endl;
    79     return 0;
    80 }

    四.选择排序

     1 #include<iostream>
     2 #include<stdlib.h>
     3 using namespace std;
     4 
     5 template <typename T>
     6 void SelectionSort(T A[], int length)
     7 {
     8     if (A != NULL && length > 0)
     9     {
    10         for (int i = 0; i < length - 1; i++)
    11         {
    12             int smallest = i;
    13             for (int j = i + 1; j < length; j++)
    14             {
    15                 if (A[j] < A[smallest])
    16                 {
    17                     smallest = j;
    18                 }
    19             }
    20             T temp = A[i];
    21             A[i] = A[smallest];
    22             A[smallest] = temp;
    23         }
    24     }
    25 }
    26 
    27 int main()
    28 {
    29     double A[] = { 1.1, -2.1, 3, 3, 4, -10, 4, 2.6 ,20, 10};
    30     SelectionSort(A, 10);
    31     for (int i = 0; i < 10; i++)
    32     {
    33         cout << A[i] << " ";
    34     }
    35     cout << endl;
    36     return 0;
    37 }

    由于每次都是选取未排序序列A中的最小元素x与A中的第一个元素交换,因此跨距离了,很可能破坏了元素间的相对位置,因此选择排序是不稳定的!比如:3  3  2

    效率O(n²),适用于排序小的列表

    五.冒泡排序

     1 #include<iostream>
     2 #include<stdlib.h>
     3 using namespace std;
     4 
     5 template <typename T>
     6 void BubbleSort(T A[], int length)
     7 {
     8     if (A != NULL && length > 0)
     9     {
    10         for (int i = length - 1; i > 0; i--)
    11         {
    12             for (int j = 0; j < i; j++)
    13             {
    14                 if (A[j] > A[j + 1])
    15                 {
    16                     T temp = A[j + 1];
    17                     A[j + 1] = A[j];
    18                     A[j] = temp;
    19                 }
    20             }
    21         }
    22     }
    23 }
    24 
    25 int main()
    26 {
    27     double A[] = { 1.1, -2.1, 3, 3, 4, -10, 4, 2.6 ,20, 10};
    28     BubbleSort(A, 10);
    29     for (int i = 0; i < 10; i++)
    30     {
    31         cout << A[i] << " ";
    32     }
    33     cout << endl;
    34     return 0;
    35 }

    排序过程中只交换相邻两个元素的位置。因此,当两个数相等时,是没必要交换两个数的位置的。所以,它们的相对位置并没有改变,冒泡排序算法是稳定的!

    效率 O(n²),适用于排序小列表

    六.堆排序

     1 #include<iostream>
     2 #include<stdlib.h>
     3 using namespace std;
     4 
     5 int Parent(int i)
     6 {
     7     return i / 2;
     8 }
     9 
    10 int Left(int i)
    11 {
    12     return 2 * i;
    13 }
    14 
    15 int Right(int i)
    16 {
    17     return 2 * i + 1;
    18 }
    19 
    20 template <typename T>
    21 void MaxHeapify(T A[], int i, int length)
    22 {
    23     if (i > 0)
    24     {
    25         int l = Left(i);
    26         int r = Right(i);
    27         int largest;
    28         if (l <= length && A[l - 1] > A[i - 1])
    29         {
    30             largest = l;
    31         }
    32         else
    33         {
    34             largest = i;
    35         }
    36         if (r <= length && A[r - 1] > A[largest - 1])
    37         {
    38             largest = r;
    39         }
    40         if (largest != i)
    41         {
    42             T temp = A[i - 1];
    43             A[i - 1] = A[largest - 1];
    44             A[largest - 1] = temp;
    45             MaxHeapify(A, largest, length);
    46         }
    47     }
    48 }
    49 
    50 template <typename T>
    51 void BuildMaxHeap(T A[], int length)
    52 {
    53     for (int i = length / 2; i >= 1; i--)
    54     {
    55         MaxHeapify(A, i, length);
    56     }
    57 }
    58 
    59 template <typename T>
    60 void HeapSort(T A[], int length)
    61 {
    62     if (A != NULL && length > 0)
    63     {
    64         int heapSize = length;
    65         BuildMaxHeap(A, length);
    66         for (int i = length; i >= 2; i--)
    67         {
    68             T temp = A[0];
    69             A[0] = A[i - 1];
    70             A[i - 1] = temp;
    71 
    72             heapSize--;
    73             MaxHeapify(A, 1, heapSize);
    74         }
    75     }
    76 }
    77 
    78 int main()
    79 {
    80     double A[] = { 1.1, -2.1, 3, 3, 4, -10, 4, 2.6 ,20, 10};
    81     HeapSort(A, 10);
    82     for (int i = 0; i < 10; i++)
    83     {
    84         cout << A[i] << " ";
    85     }
    86     cout << endl;
    87     return 0;
    88 }

    堆排序的最坏时间复杂度为O(nlgn)。堆排序的平均性能较接近于最坏性能。由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。堆排序是就地排序,辅助空间为O(1),它是不稳定的排序方法。 

    七.计数排序

     1 #include<iostream>
     2 using namespace std;
     3 
     4 void CountingSort(int A[], int k, int length)
     5 {
     6     if (A == NULL || k < 0 || length <= 0)
     7     {
     8         return;
     9     }
    10     int *C = new int[k + 1];
    11     int *B = new int[length];
    12     for (int i = 0; i <= k; i++)
    13     {
    14         C[i] = 0;
    15     }
    16     for (int j = 0; j < length; j++)
    17     {
    18         C[A[j]]++;
    19     }
    20     for (int i = 1; i <= k; i++)
    21     {
    22         C[i] += C[i - 1];
    23     }
    24     for (int j = length - 1; j >= 0; j--)
    25     {
    26         B[C[A[j]] - 1] = A[j];
    27         C[A[j]]--;
    28     }
    29     for (int j = 0; j < length; j++)
    30     {
    31         A[j] = B[j];
    32     }
    33 }
    34 
    35 
    36 int main()
    37 {
    38     int A[] = { 11, 2, 3, 3, 4, 10, 0, 6 ,20, 10};
    39     CountingSort(A, 20, 10);
    40     for (int i = 0; i < 10; i++)
    41     {
    42         cout << A[i] << " ";
    43     }
    44     cout << endl;
    45     return 0;
    46 }

     稳定,适用范围比较局限,非负整数,最大值不是很大的情况,数值分布跨度比较小。

    八.基数排序

     1 #include<iostream>
     2 #include<math.h>
     3 using namespace std;
     4 
     5 void CountingSort(int A[], int k, int length, int i)
     6 {
     7     int *C = new int[k];
     8     int *B = new int[length];
     9     for (int i = 0; i < k; i++)
    10     {
    11         C[i] = 0;
    12     }
    13     for (int j = 0; j < length; j++)
    14     {
    15         C[(int)(A[j] / pow(10.0, i - 1)) % 10]++;
    16     }
    17     for (int i = 1; i < k; i++)
    18     {
    19         C[i] += C[i - 1];
    20     }
    21     for (int j = length - 1; j >= 0; j--)
    22     {
    23         B[C[(int)(A[j] / pow(10.0, i - 1)) % 10] - 1] = A[j];
    24         C[(int)(A[j] / pow(10.0, i - 1)) % 10]--;
    25     }
    26     for (int j = 0; j < length; j++)
    27     {
    28         A[j] = B[j];
    29     }
    30 }
    31 
    32 void RadixSort(int A[], int n, int radix, int length)
    33 {
    34     if (A == NULL || n <= 0 || radix <= 1 || length <= 0)
    35     {
    36         return;
    37     }
    38     for (int i = 1; i <= n; i++)
    39     {
    40         CountingSort(A, radix, length, i);
    41     }
    42 }
    43 
    44 int main()
    45 {
    46     int A[] = { 111, 2, 37, 3, 4, 100, 0, 600, 20, 10};
    47     RadixSort(A, 3, 10, 10);
    48     for (int i = 0; i < 10; i++)
    49     {
    50         cout << A[i] << " ";
    51     }
    52     cout << endl;
    53     return 0;
    54 }

    基数排序过程中不改变元素的相对位置,因此是稳定的!特别适用于非负整数且length >> n的情况。

  • 相关阅读:
    第一次上传文件到linux服务器
    @JsonFormat与@DateTimeFormat的区别
    Tomcat端口被占用处理
    简单的Tomcat部署
    PHP源码加密,zend guard与ioncube
    PHP计算年龄
    My97DatePicker时间控件 JQuery UI
    php二维数组自定义排序
    CodeSmith Generator 7.0.2激活步骤
    SQL Server Management Studio 2008版本的安装
  • 原文地址:https://www.cnblogs.com/wanderingzj/p/5269979.html
Copyright © 2011-2022 走看看