码海拾遗:常用的其中排序算法

排序算法大致可分为两类:

  比较排序,时间复杂度一般在O(nlogn) ~ O(n^2)之间,主要有冒泡排序、选择排序、插入排序、希尔排序、快速排序、归并排序、堆排序

  非比较排序,时间复杂度可达到O(n),主要有计数排序、基数排序

本文主要介绍常用的其中比较排序。

   1、冒泡排序

  说明:冒泡排序是一种非常简单的排序算法,需要重复遍历需要排序的所有元素,依次比较相邻的两个元素,如果顺序错误就将两者位置调换,知道没有元素需要交换位置,排序结束。

  平均时间复杂度:O(n^2)。

  稳定性:稳定。

  2、选择排序

  说明:开始时找到序列中的最小(大)元素,放到序列的起始位置作为已排序序列,然后再从剩余未排序序列中找的最小(大)的元素,放到已排序序列的末尾;以此类推,直至所有元素都排序完成。

  平均时间复杂度:O(n^2)。

  稳定性:不稳定。

  3、插入排序

  说明:将未排序的元素在已排序的序列中从后向前找到相应的位置插入。

  平均时间复杂度:O(n^2)。

  稳定性:稳定

  4、希尔排序

  说明:又称递减增量排序,是插入排序的一种高速改进版本。

  平均时间复杂度:希尔排序的时间复杂度与增量的选取有关,当增量为1时,为O(n^2),Hibbard增量的希尔排序的时间复杂度为O(N3/2)。

  稳定性:不稳定

  5、快速排序

  说明:使用分而治之的策略把一个序列分成两个子序列

  平均时间复杂度:O(nlogn)

  稳定性:不稳定

  6、归并排序

  说明:建立在归并操作上的一种排序算法,由冯·诺依曼首次提出。

  平均时间复杂度:O(nlogn)

  稳定性:稳定

  7、堆排序

  说明:利用堆这种数据结构设计的排序算法,堆是一种近似完全二叉树的结构,并满足性质:以大顶堆为例,父节点的元素总大于子节点的元素。

  平均时间复杂度:O(nlogn)

  稳定性:不稳定

  实现:my_sort.h

 1 #pragma once
 2 
 3 //两值交换
 4 void swap(int& a, int& b);
 5 void swap(int arr[],int i,int j);
 6 
 7 //选择排序
 8 void selectSort(int arr[], int arrSize);
 9 
10 //插入排序
11 void insertSort(int arr[], int arrSize);
12 
13 //冒泡排序
14 void bubbleSort(int arr[], int arrSize);
15 
16 //希尔排序
17 void shellSort(int arr[], int arrSize);
18 
19 //快速排序
20 void quickSort(int arr[],int start,int end);
21 
22 //归并排序
23 void mergeSort(int a[], int first, int last, int temp[]);
24 //将两个有序数列a[first...mid]和a[mid+1...last]合并。
25 void mergeArray(int a[], int first, int mid, int last, int temp[]);
26 
27 //堆排序
28 void heapSort(int arr[], int arrSize);
29 //建堆
30 int buildHeap(int arr[], int arrSize);
31 //从指定节点开始向下进行堆调整
32 void heap(int arr[], int i, int size);

my_sort.cpp

  1 #include "my_sort.h"
  2 
  3 void swap(int & a, int & b)
  4 {
  5     int tmp = a;
  6     a = b;
  7     b = tmp;
  8 }
  9 
 10 void swap(int arr[], int i, int j)
 11 {
 12     int tmp = arr[i];
 13     arr[i] = arr[j];
 14     arr[j] = tmp;
 15 }
 16 
 17 //选择排序
 18 void selectSort(int arr[], int arrSize)
 19 {
 20     int min = 0;//初始时最小值位置
 21     for (int i = 0; i < arrSize - 1; ++i)
 22     {
 23         min = i;
 24         for (int j = i + 1; j < arrSize; ++j)
 25             if (arr[min] > arr[j])
 26                 min = j;
 27 
 28         if (min != i)
 29             swap(arr[min], arr[i]);
 30     }
 31 }
 32 
 33 //插入排序
 34 void insertSort(int arr[], int arrSize)
 35 {
 36     int i, j;
 37     for (i = 1; i < arrSize; ++i)
 38     {
 39         int tmp = arr[i];
 40         for (j = i; j > 0 && tmp<arr[j-1]; --j)
 41         {
 42             arr[j] = arr[j - 1];
 43         }
 44         arr[j] = tmp;
 45     }
 46 }
 47 
 48 //冒泡排序
 49 void bubbleSort(int arr[], int arrSize)
 50 {
 51     for (int i = 0; i < arrSize; ++i)
 52     {
 53         for (int j = 1; j < arrSize - i; ++j)
 54         {
 55             if (arr[j] < arr[j - 1])
 56                 swap(arr[j], arr[j - 1]);
 57         }
 58     }
 59 }
 60 
 61 //希尔排序
 62 void shellSort(int arr[], int arrSize)
 63 {
 64     int step = arrSize / 2;//设置步长
 65     int i, j;
 66     int tmp;
 67     while (step >= 1)
 68     {
 69         for (i = step; i < arrSize; ++i)
 70         {
 71             tmp = arr[i];
 72             j = i - step;
 73             while (j > 0 && arr[j] > tmp)
 74             {
 75                 arr[j + step] = arr[j];
 76                 j -= step;
 77             }
 78             arr[j + step] = tmp;
 79         }
 80         step /= 2;
 81     }
 82 }
 83 
 84 //快速排序
 85 void quickSort(int arr[], int start, int end)
 86 {
 87     if (start >= end)
 88         return;
 89 
 90     int i = start;//起始位置
 91     int j = end;//最后一个元素的位置
 92 
 93     //基准值
 94     int tmp = arr[start];//以起始位置为基准
 95 
 96     while (i < j)
 97     {
 98         while (i < j&&arr[j] >= tmp)
 99             j--;
100         if (i < j)
101         {
102             arr[i] = arr[j];
103             i++;
104         }
105 
106         while (i < j&&arr[i] < tmp)
107             i++;
108         if (i < j)
109         {
110             arr[j] = arr[i];
111             j--;
112         }
113     }
114 
115     arr[i] = tmp;
116 
117     quickSort(arr, start, i - 1);
118     quickSort(arr, i + 1, end);
119 
120 }
121 
122 //将两个有序数列a[first...mid]和a[mid+1...last]合并。
123 void mergeArray(int a[], int first, int mid, int last, int temp[])
124 {
125     int i = first;    // 第一个有序序列的开始下标
126     int j = mid + 1;    // 第2个有序序列的开始下标
127 
128     int length = 0;
129     // 合并两个有序序列
130     while (i <= mid && j <= last)
131     {
132         // 找二者中比较小的数
133         if (a[i] < a[j])
134         {
135             temp[length] = a[i];
136             i++;
137         }
138         else
139         {
140             temp[length] = a[j];
141             j++;
142         }
143         length++;
144     }
145     // 还剩下一个有序序列中有数据
146     while (i <= mid)
147     {
148         temp[length] = a[i];
149         i++;
150         length++;
151     }
152     while (j <= last)
153     {
154         temp[length++] = a[j++];
155     }
156 
157     // 覆盖原来位置的无序序列
158     for (int i = 0; i < length; ++i)
159     {
160         // 找到原来 的第一个有序序列的开始位置 - 开始覆盖
161         a[first + i] = temp[i];
162     }
163 }
164 //归并排序
165 void mergeSort(int a[], int first, int last, int temp[])
166 {
167     // 递归结束的条件
168     if (first == last)
169     {
170         return;
171     }
172     // 从中间位置拆分
173     int mid = (first + last) / 2;
174     // 拆分
175     // 左半边
176     mergeSort(a, first, mid, temp);
177     // 右半边
178     mergeSort(a, mid + 1, last, temp);
179     // 合并两个有序序列
180     mergeArray(a, first, mid, last, temp);
181 }
182 
183 //堆排序
184 void heapSort(int arr[], int arrSize)
185 {
186     int heapSize = buildHeap(arr, arrSize);
187     while (heapSize > 1)
188     {
189         swap(arr, 0, --heapSize);
190         heap(arr, 0, heapSize);
191     }
192 
193 }
194 //建堆
195 int buildHeap(int arr[], int arrSize)
196 {
197     int heapSize = arrSize;
198     for (int i = heapSize / 2 - 1; i >= 0; i--)
199         heap(arr, i, heapSize);
200     return heapSize;
201 }
202 //从指定节点开始向下进行堆调整
203 void heap(int arr[], int i, int size)
204 {
205     int leftChild = 2 * i + 1;
206     int rightChild = 2 * i + 1;
207     int max = i;
208 
209     if (leftChild<size&&arr[leftChild]>arr[max])
210         max = leftChild;
211     if (rightChild<size&&arr[rightChild]>arr[max])
212         max = rightChild;
213     if (max != i)
214     {
215         swap(arr, i, max);
216         heap(arr, max, size);
217     }
218 }

  排序算法的稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,则称这种排序算法是稳定的;否则称为不稳定的。

  源码地址:https://github.com/MasterMeng/sort

原文地址:https://www.cnblogs.com/lianshuiwuyi/p/7647984.html