本次排序都是按照升序排的
冒泡排序
void bubbleSort(vector<int>& nums)
{
int n=nums.size();
for(int i=0;i<n-1;i++)
{
bool swapped=false;
for(int j=0;j<n-1-i;j++)
{
if(nums[j]>nums[j+1])
{
swap(nums[j],nums[j+1]);
swapped=true;
}
}
if(!swapped)
break;
}
}
//算法原理: 一共排序n-1次,每一次排序,相邻元素两两比较,一共比较n-1-i次,最后排出一个元素放在数组末尾,n-1次后,排序完成。
// 若还没有到第n-1次排序,比较元素没有交换位置,则排序已完成,可提前结束排序。
//时间复杂度: O(N^2)
//空间复杂度: O(1)
//稳定性: 稳定
选择排序
void SelectSort(vector<int>& nums)
{
int n=nums.size();
for(int i=0;i<n-1;i++)
{
int minIndex=i;
for(int j=i+1;j<n;j++)
{
if(nums[j]<nums[minIndex])
{
minIndex=j;
}
}
swap(nums[i],nums[minIndex]);
}
}
//算法原理: 需要选择n-1次基准元素,从下标为0开始选取,然后与未排序的元素比较,找到元素最小的下标,交换基准元素和最小元素,一次排序
// 已完成。一共排序n-1次。
//时间复杂度: O(N^2)
//空间复杂度: O(1)
//稳定性: 不稳定
插入排序
void InsertSort(vector<int>& nums)
{
int n=nums.size();
for(int i=1;i<n;i++)
{
int key=nums[i],j=i-1;
while(j>=0&&nums[j]>key)
{
nums[j+1]=nums[j];
j--;
}
nums[j+1]=key;
}
}
//算法原理: 从下标为1开始,令其为key,然后插入到已排序的元素中,找到应该插入的位置。
//时间复杂度: O(N^2)
//空间复杂度: O(1)
//稳定性: 稳定
希尔排序
void ShellSort(vector<int>& nums)
{
int n=nums.size();
for(int gap=n/2;gap>0;gap/=2)
{
for(int i=gap;i<n;i++)
{
int key=nums[i],j=i-gap;
while(j>=0&&nums[j]>key)
{
nums[j+gap]=nums[j];
j-=gap;
}
nums[j+gap]=key;
}
}
}
//算法原理: 插入排序的优化,按照gap为间隔,每次排序是预排序,使数组趋于有序化,当gap等于1时,才是真的排序
//时间复杂度: O(N^2)
//空间复杂度: O(1)
//稳定性: 不稳定
快速排序
快排思想:
int _QuickSort(vector<int> &nums, int left, int right)
{
int key = left;
left++;
while (left <= right)
{
while (left <= right && nums[left] < nums[key])
left++;
while (left <= right && nums[right] > nums[key])
right--;
if (left <= right)
swap(nums[left++], nums[right--]);
}
swap(nums[key], nums[right]);
return right;
}
void QuickSort(vector<int> &nums, int left, int right)
{
if (left > right)
return;
int key = _QuickSort(nums, left, right);
QuickSort(nums, left, key - 1);
QuickSort(nums, key + 1, right);
}
//算法原理: 任取待排序元素中的某元素作为基准元素,使左边元素都小于基准元素,右边元素都大于基准元素,然后重复该过程,直到所有元素都
// 排序完成。
//时间复杂度: O(NlogN)
//空间复杂度: O(logN)
//稳定性: 不稳定
归并排序
void MergeSort(vector<int> &nums, int left, int right)
{
if (left >= right) return;
int mid = (left + right) >> 1;
MergeSort(nums, left, mid);
MergeSort(nums, mid + 1, right);
vector<int> tmp(right-left+1);
int cur1 = left, cur2 = mid + 1, i = 0;
while (cur1 <= mid && cur2 <= right)
tmp[i++] = nums[cur1] < nums[cur2] ? nums[cur1++] : nums[cur2++];
while (cur1 <= mid)
tmp[i++] = nums[cur1++];
while (cur2 <= right)
tmp[i++] = nums[cur2++];
for (int i = left; i <= right; i++)
nums[i] = tmp[i - left];
}
//算法原理: 将数组分为两部分,不断的递归,直到数组元素为1或者不能再分,然后合并两个有序数组。
//时间复杂度: O(NlogN)
//空间复杂度: O(N)
//稳定性: 稳定
堆排序
void AdjustDown(vector<int>& nums,int n,int parent)
{
int child=parent*2+1;
while(child<n)
{
if(child+1<n && nums[child+1]>nums[child]) child=child+1;
if(nums[child]>nums[parent])
{
swap(nums[child],nums[parent]);
parent=child;
child=parent*2+1;
}
else
{
break;
}
}
}
void HeapSort(vector<int>& nums)
{
int n=nums.size();
//构建大根堆,从最后一个非叶子节点开始
for(int i=(n-1-1)/2;i>=0;i--)
{
AdjustDown(nums,n,i);
}
//排序
int end=n-1;
while(end>=0)
{
swap(nums[0],nums[end]);
AdjustDown(nums,end,0);
end--;
}
}
//算法原理: 先构建最大堆,然后交换堆顶元素和最后一个元素,这样最后一个元素就是最大的了,然后再建堆,这样不断循环。
//时间复杂度: O(NlogN)
//空间复杂度: O(N)
//稳定性: 稳定
基数排序
void RadixSort(std::vector<int>& nums) {
int maxVal=*max_element(nums.begin(),nums.end());
int maxDigits=0;
while(maxVal)
{
maxVal/=10;
maxDigits++;
}
vector<queue<int>> buckets(10);
for(int i=0;i<maxDigits;i++)
{
for(int num : nums)
{
int bucketIndex=num/static_cast<int>(pow(10,i))%10;
buckets[bucketIndex].push(num);
}
int index=0;
for(auto& bucket : buckets)
{
while(!bucket.empty())
{
nums[index++]=bucket.front();
bucket.pop();
}
}
}
}
//算法原理: 按照位数排序,按照位数把元素分配到对应的桶中,然后依据先进先出的顺序再收集到数组中,这样依次排个位,十位,百位。
//时间复杂度: O(NlogN)
//空间复杂度: O(N)
//稳定性: 稳定