可用leetcode第88题来验证自己所写的排序算法是否正确
88. 合并两个有序数组
代码如下:
注意,以下版本是在vs上进行编写的,写88题时需要先将nums2的数组元素复制到nums1数组的后半段,再调用这些排序函数
using namespace std;
# include<iostream>
# include<vector>
//打印数据
void print_vec(const vector<int>& vec) {
for (auto it = vec.begin(); it != vec.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
// 冒泡排序 稳定排序 时间复杂度O(n*n),空间复杂度O(1)
void bubbleSort(vector<int>& vec) {
// 两两比较
int n = vec.size();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (vec[j] > vec[j + 1]) swap(vec[j], vec[j + 1]);
}
}
}
// 插入排序 稳定排序 时间复杂度O(n*n),空间复杂度O(1)
void insertSort(vector<int>& vec) {
// 每次将新元素插入到已排序的有序队列里面
int n = vec.size();
for (int i = 1; i < n; i++) {
if (vec[i] > vec[i - 1]) continue;
int temp = i;//记录新元素每次交换后的位置
for (int j = i - 1; j >= 0; j--) {
if (vec[temp] < vec[j]) {//只要比排序数小,就交换两者位置
swap(vec[temp], vec[j]);
temp = j;//记录新元素的位置
}
else break;
}
}
}
//归并排序 稳定排序 时间复杂度O(n*logn),空间复杂度O(n)
//算法思想
//1、把长度为n的输入序列分成两个长度为n / 2的子序列;
//2、对这两个子序列分别采用归并排序;
//3、 将两个排序好的子序列合并成一个最终的排序序列。
void mergeSort(vector<int>& vec,vector<int> &data,int start,int end) {
//vec为需要排序的数组,data为放置排序好的子序列的数组,取闭区间[start,end]
if (start >= end) return;
int mid = start + (end - start) / 2;
mergeSort(vec, data, start, mid);
mergeSort(vec, data, mid + 1, end);
//p1为前半个数组的头指针,p2为后半个数组的头指针,p为data数组的头指针
int p1 = start, p2 = mid + 1, p = start;
//int len = (end - start) * 2;
for (; p <= end; p++) {
//这里用if进行判断的时候很重要,容易把情况漏掉
//刚开始我写成if(p1<=mid&&vec[p1]<vec[p2]){} else{} ,这样写漏掉了一些情况
if (p1<=mid&&p2>end) {
data[p] = vec[p1++];
}
else if(p1>mid&&p2<=end){
data[p] = vec[p2++];
}
else {//两个都没越界
data[p] = vec[p1] > vec[p2] ? vec[p2++] : vec[p1++];
}
}
for (int i = start; i <= end; i++) {
vec[i] = data[i];
}
}
// 快速排序 不稳定排序 时间复杂度O(n*log n),空间复杂度O(logn)(递归会使用栈)
//1、选取第一个数为基准
//2、将比基准小的数交换到前面,比基准大的数交换到后面
//3、对左右区间重复第二步,直到各区间只有一个数
void quickSort(vector<int>& vec,int index_start,int index_end) {
//使用递归 传入整个数组和需要处理的数据起始位置[index_start,index_end]
if (index_end <= index_start) return;//递归终止条件
int temp = index_start;//选取第一个数为基准
for (int i = temp + 1; i <= index_end;i++ ) {
if (vec[i] < vec[temp]) {
for (int j = i; j > temp; j--) {
//vec[i]依次和temp开始一直到i-1位置的数进行交换,直到i位置数字换到vec[temp]前面去
swap(vec[j], vec[j - 1]);//两两交换
}
temp++;//记录基准数更新后的位置
}
}
quickSort(vec, index_start, temp - 1);
quickSort(vec, temp + 1, index_end);
}
// 希尔排序 不稳定排序 时间复杂度O(n*n),空间复杂度O(1)
// 插入排序的变种,局部有序
void insert_sort(vector<int>&vec, int gap,int start_index) {//将start_index插入到本组中正确的位置
int insert_num = vec[start_index];
int i = start_index - gap;
for (; i >=0&&vec[i]>insert_num; i=i-gap) {
vec[i + gap] = vec[i];
}
vec[i + gap] = insert_num;
}
void shellSort(vector<int>& vec) {
for (int gap = vec.size() / 2; gap >= 1; gap /= 2) {
for (int j = gap; j < vec.size(); j++) {
insert_sort(vec, gap, j);
}
}
}
// 选择排序 不稳定排序 时间复杂度O(n*n),空间复杂度O(1)
void selectSort(vector<int>& vec) {
//每次选择剩余元素里面的最小值放到第一个循环的位置上
int n = vec.size();
for (int i = 0; i < n; i++) {
int minNum = i;
for (int j = i + 1; j < n; j++) {
if (vec[minNum] > vec[j]) minNum = j;;
}
swap(vec[i], vec[minNum]);
}
}
// 堆排序 不稳定排序 时间复杂度O(n*logn),空间复杂度O(1)
//堆排序的基本思想是:
//将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。
//将其与末尾元素进行交换,此时末尾就为最大值。
//然后将剩余n - 1个元素重新构造成一个堆,这样会得到n个元素的次小值。
//如此反复执行,便能得到一个有序序列了
//void heapify(vector<int>& vec, int index) {
//
//}
void adjust_maxheap(vector<int>& vec,int end) {//调整为大顶堆
//end为需要调整的最大位置,闭区间[0,end]
//节点i的父节点:(i-1)/2 左孩子节点:2i+1,右孩子节点:2i+2
for (int i = (end - 1) / 2; i >= 0; i--) {//(end-1)/2为倒数第二层的右边最后一个非叶子结点
//其实就是每次选择非叶子结点和它的孩子节点为一组,
//把这组节点的最大值找出来当做父节点,再从右往左,从下到上依次循环操作
int left = 2 * i + 1;
int right = 2 * i + 2;
if (right > end) {
//只有左孩子节点
//这种情况最多出现一次
if (vec[left] > vec[i]) {
swap(vec[left], vec[i]);
}
}
else {//两个孩子节点都有
int index = vec[left] > vec[right] ? left : right;
if (vec[index] > vec[i]) {
swap(vec[index], vec[i]);
}
}
}
}
void heapSort(vector<int>& vec) {
for (int i = 0; i < vec.size()-1; i++) {
adjust_maxheap(vec, vec.size()-1 - i);
swap(vec[0], vec[vec.size() - 1 - i]);//把调整好的大顶堆的第一个值和end进行交换
}
}
// 计数排序
void countSort(vector<int>& vec) {
}
int main() {
vector<int> vec{ 10,8,4,6,9,10,123,6,2,14,3,8,5 };
//cout << "------快速排序-------" << endl;
//quickSort(vec,0,vec.size()-1);
//print_vec(vec);
//cout << "------归并排序-------" << endl;
//vector<int> data(vec.size(), 0);
//mergeSort(vec,data,0,vec.size()-1);
//print_vec(data);
cout << "------堆排序-------" << endl;
heapSort(vec);
print_vec(vec);
return 0;
}