本次排序都是按照升序排的
冒泡排序
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) //稳定性: 稳定