本文基于C++完成实现了快速排序,归并排序,堆排序。
代码结构如下
-- quickSort 递归实现快速排序
-- mergeSort 递归实现归并排序
------ merge 实现两个有序数组的归并
-- heapSort 实现堆排序
------ heapify 实现从一个数组转化为堆
------ down 实现 调节以该顶点为根的堆
快速排序
void quickSort(vector<int> & arr, int lo, int hi) {
if (lo >= hi) return;
int m = lo + rand()%(hi-lo+1), i = lo, j = hi;
int p = arr[m];
swap(arr[lo], arr[m]);
while(i<j) {
while (i < j && p <= arr[j) j--;
if (i<j) arr[i]=arr[j], i++;
while (i < j && arr[i] <= p) i++;
if (i<j) arr[j]=arr[i], j--;
}
arr[i]=p;
quickSort(arr, lo, i-1);
quickSort(arr, i+1, hi);
return;
}
- 选取pivot点
- 找到pivot点的最终排序位置,即pivot点左边都小于等于pivot,右边都大于等于pivot;
- 迭代快速排序pivot左边的数组
- 迭代快速排序pivot右边的数组
注意 if(i<j)
不可以少。注意边界条件。
完成
归并排序
void mergeSort(vector<int> & arr, int low, int high) {
if (low >= high) return;
int mid = low + (high-low)/2;
mergeSort(arr, low, mid);
mergeSort(arr, mid+1,high);
merge(arr, low, mid, high);
return;
}
void merge(vector<int> & arr, int lo, int mi, int hi) {
// [lo,mi] [mi+1,hi]
vector<int> temp(hi-lo+1, 0);
int l1 = lo, l2 = mi+1, tj = 0;
while (l1 <= mi && l2 <= hi) {
if (arr[l1] <= arr[l2]) {
temp[tj++] = arr[l1++];
} else {
temp[tj++] = arr[l2++];
}
}
while (l1 <= mi) temp[tj++]=arr[l1++];
while (l2 <= hi) temp[tj++]=arr[l2++];
tj = 0;
for (int i=lo; i<=hi;i++) arr[i]=temp[tj++];
}
归并排序的核心思想是二分,对原来的数组分为两个数组进行排序,最后归并两个有序数组。
- 对数组平均划分为两个区间
- 对两个区间分别进行归并排序
- 对上述两个已经排序的数组进行归并, 即
merge
函数,实现对两个有序数组的归并。
堆排序
- 使一个数组构建一个大根堆,大小和数组同尺寸。
heapify
- 弹出堆顶,即最大元素,放入arr[n-1]位置。将原来的arr[n-1]放入堆顶,即arr[0]。
swap
- 堆大小减小一个尺度,并从堆顶更新当前堆,维护大根堆的结构 ,
down
- 弹出堆顶直至堆大小为1.
堆的思想则是维持半有序的结构,大根堆,即堆顶元素大于等于其他元素;小根堆,即堆顶元素小于等于其他元素。为了实现数组从小到大的排序,我们可以构建一个大根堆,每次弹出堆顶,放入数组的最后一个位置,减小堆的大小,然后更新当前堆,使其符合大根堆的结构。
void heapSort(vector<int> & arr) {
if (arr.size() <= 1) return;
// 从小到大排序 所以是大根堆, 每次弹出将最大值放在最后一位, 堆空间缩小一个。
heapify(arr);
int n = arr.size();
for (int i = n-1; i>=1; i--) {
swap(arr[0], arr[i]);
down(arr, 0, i); //堆大小缩小一个位置
}
return;
}
void heapify(vector<int> & arr) {
int k = arr.size();
int lastNotLeaf = ((k-1)>>1);
for (int i = lastNotLeaf; i>=0;--i) {
down(arr, i, k);
}
return;
}
void down(vector<int> & arr, int pos, int k) {
if (k <= 1) return;
// 沿着当前节点不符合 大根堆 k代表堆的大小 前k个数据构成大根堆
int _t = arr[pos];
while (pos < k) {
int r = (pos+1)<<1;
int l = r-1;
if (l >= k) break; // 这里判断不能出错!! 啊 后面判断r有没有出界 这里先判断l是否出界
int _max = r>=k? l:( (arr[l]<arr[r])? r:l); // 大根堆 保留最大值
if (arr[_max] <= _t) break; // 如果已经满足条件 就退出循环
arr[pos] = arr[_max];
pos = _max;
}
arr[pos] = _t;
return;
}
完整代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 将给定数组排序
* @param arr int整型vector 待排序的数组
* @return int整型vector
*/
vector<int> MySort(vector<int>& arr) {
// write code here
// quickSort(arr, 0, arr.size()-1);
// mergeSort(arr, 0, arr.size()-1);
heapSort(arr);
return arr;
}
void quickSort(vector<int> & arr, int lo, int hi) {
if (lo >= hi) return;
int m = lo + rand()%(hi-lo+1), i = lo, j = hi;
int p = arr[m];
swap(arr[lo], arr[m]);
while(i<j) {
while (i < j && arr[j] >= p) j--;
if (i<j) arr[i]=arr[j], i++;
while (i < j && arr[i] <= p) i++;
if (i<j) arr[j]=arr[i], j--;
}
arr[i]=p;
quickSort(arr, lo, i-1);
quickSort(arr, i+1, hi);
return;
}
void mergeSort(vector<int> & arr, int low, int high) {
if (low >= high) return;
int mid = low + (high-low)/2;
mergeSort(arr, low, mid);
mergeSort(arr, mid+1,high);
merge(arr, low, mid, high);
return;
}
void merge(vector<int> & arr, int lo, int mi, int hi) {
// [lo,mi] [mi+1,hi]
vector<int> temp(hi-lo+1, 0);
int l1 = lo, l2 = mi+1