快速排序
关键点:
1、快排的思想很简单:每次以当前序列第一个元素为划分数据的监视哨,然后不断的遍历双指针,找到交换的位置,进行交换,直到两个指针相遇。
2、细节点:在遍历和赋值的时候一定要判断两个指针的位置。
#include<iostream>
#include<vector>
#include <algorithm>
using namespace std;
void quickSortCore(vector<int> & nums, int left, int right){
int l = left, r = right;
int temp = nums[left];
if(left>=right) return;
while(left<right){
// 在坐标不断变换的过程中,要不断的判断界限的问题
while(nums[right]>temp && left<right) right--;
// 在可能满足交换条件后,一定要判断双指针的大小问题,如果满足条件次才能进行赋值操作
if(left < right) nums[left++] = nums[right];
while(nums[left]<= temp && left<right) left++;
if(left < right) nums[right--] = nums[left];
}
nums[left] = temp;
quickSortCore(nums, l, left-1);
quickSortCore(nums, left+1, r);
}
void quickSort(vector<int> & nums, int len){
int left=0, right = len-1;
if(left >= right) return;
quickSortCore(nums, left, right);
}
int main()
{
vector<int> nums = {2, 3, 1, 5, 9, 10, 4, 6, 7, 1, 3};
quickSort(nums, 11);
for(auto i: nums){
cout<<i<<",";
}
cout<<endl;
return 0;
}
时间复杂度:平均:O(nlog(n)) 最坏:O(n^2)
空间复杂度:O(log(n))
稳定性:快速排序是一种不稳定的排序方法。
时间复杂度、空间复杂度 转载:https://blog.csdn.net/yuzhihui_no1/article/details/44198701
归并排序:
关键点:
我们将归并排序分为两步:
1、merge:我们不断的将数组进行一分为二,知道不能再分为止
2、sort:我们将分好的数组,两两进行比较,这两相当于将两个已经排好序的数组整合成一个有序数组,最终做到整体排序的结果。
#include<iostream>
#include<vector>
#include <algorithm>
using namespace std;
void sort(vector<int>& nums, vector<int> temp, int left, int middle, int right){
if (left <= middle && middle+1 <= right && left < right){
int index = left, r=middle+1, save=left;
while(left <= middle && r <= right){
if(nums[left] < nums[r]) {
temp[index++] = nums[left++];
} else{
temp[index++] = nums[r++];
}
}
while(r <= right) temp[index++] = nums[r++];
while(left <= middle) temp[index++] = nums[left++];
for(int i=save; i<=right; i++) nums[i] = temp[i];
} else{
return;
}
}
void merge(vector<int>& nums, vector<int> temp, int left, int right){
if(left < right){
int middle = (left + right) / 2;
merge(nums, temp, left, middle);
merge(nums, temp, middle+1, right);
sort(nums, temp, left, middle, right);
}
}
int main()
{
int len = 11;
vector<int> nums = {2, 3, 1, 5, 9, 10, 11, 7, 8, 0, 2};
vector<int> temp(len, 0); // 用来临时保存排序后的结果
merge(nums, temp, 0, len-1);
for(auto i: nums){
cout<<i<<",";
}
cout<<endl;
return 0;
}
时间复杂度:最好: O(Nlog(N)) 平均 : O(Nllog(N)) 最坏: O(Nlog(N))
空间复杂度:空间复杂度:O(N)
稳定性:归并排序是稳定的排序算法。
堆排序【我们以大顶堆为例】
关键点:
堆排序:
1、根据初始的排序,先将序列调整为大顶堆或者小顶堆
1.1 整体调整,是从最后一个拥有子节点的根节点进行调整
1.2 调整整体的时候,用child 来记录需要进行调整节点的下标,如果满足条件不断的比较交换后节点的子节点的情况
2、依次把末尾数字和头部数据交换,在整体调整,得到排序结果。
#include<iostream>
#include<vector>
#include <algorithm>
using namespace std;
void Adjust(vector<int>& nums, int index, int len){
int child; // 需要和根节点比较的子节点的下标
int temp; // 保存暂时需要比较的值
for(temp=nums[index]; (2*index + 1) < len; index=child){
child = 2*index+1;
// 如果右孩子存在,并且右孩子的值大于左孩子,那么需要进行交换
if((2*index+2)<len && nums[2*index+2]>nums[child]) child = 2*index + 2;
if(nums[index] < nums[child]) swap(nums[index], nums[child]);
else break;
}
}
void HeapSort(vector<int> nums){
int len = nums.size();
if(len <= 1) return;
/* 1、建立大顶堆 */
// 对每一个根节点进行调整 【从上到下,从右到左,第一个根节点的下标是 : (len-1)/2 】
for(int i=(len-1)/2; i>=0; i--){
Adjust(nums, i, len);
}
/* 2、将根节点和最后一个节点进行交换,然后继续调整 (直到长度为1)*/
// 保证最大的节点的值,依次往后排
for(int j=len-1; j>0; j--){
swap(nums[0], nums[j]);
Adjust(nums, 0, j);
}
for(auto item:nums) printf("%d ", item);
printf("\n");
}
int main()
{
vector<int> nums = {2, 3, 1, 5, 9, 10, 11, 7, 8, 0, 2, 13, 4, 76, 8, -1, 99, 34};
HeapSort(nums);
return 0;
}
时间复杂度: O(Nlog(N))
空间复杂度:O(1)
稳定性:堆排序不是稳定的排序算法。