1.先来最简单的冒泡排序
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 每一轮对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。第一轮结束,最后的元素应该会是最大的数。
- 针对所有的元素重复以上的步骤n-1轮,分别倒序排好倒数第二大、倒数第三大……的元素。直到没有任何一对数字需要比较。
class Solution {
public:
vector<int> sortArray(vector<int>& nums) {
cout<<nums.size();
for(auto r = nums.begin();r<nums.end()-1;r++){
for(auto s = nums.begin();s<nums.end()-(r-nums.begin())-1;s++){
if(*s>*(s+1)){
swap(*s,*(s+1));
}
}
}
return nums;
}
};
注意内层循环时迭代器的范围,两个迭代器相减返回的是int类型,不能直接与另一个迭代器进行比较操作。
2.快速排序
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
先假设第一个元素为轴值,自右向左找一个比轴值小的数交换,再自左向右找一个比轴值大的数交换,再重复自右向左找一个比轴值小的数交换,自左向右找一个比轴值大的数交换,直到轴值左边没有比其大的数存在,右边也没有比其小的数存在,则第一轮结束。原来的一组数据被划分为以轴值为界的两组新数据
第二轮:取上一轮轴值左边的一组新数据,重复1的操作;取上一轮轴值右边的一组新数据,重复1的操作,则把最初的一组数据分成了四部分,这样便产生一个递归的思想
一直重复操作,直到数据被分的不可再分为止。
class Solution {
public:
vector<int> sortArray(vector<int>& nums) {
return my_sort(nums,nums.begin(),nums.end());
}
vector<int> my_sort(vector<int>& nums,auto it_left,auto it_right) {
//以第一个数为基准
auto it = it_left;
bool xunhuan = true;
while (xunhuan){
//从右向左,交换小于基准的数
for(auto r = it_right-1;r>=it_left;r--){
if (*r<*it){
swap(*r,*it);
it = r;
break;
}
if(r==it){
xunhuan = false;
break;
}
}
//从左向右,交换小于基准的数
for(auto r = it_left;r<it_right;r++){
if (*r>*it){
swap(*r,*it);
it = r;
break;
}
if(r==it){
xunhuan = false;
break;
}
}
}
if (it>it_left+1) {
my_sort(nums,it_left,it);
}
if (it<it_right-2) {
it++;
my_sort(nums,it,it_right);
}
return nums;
}
};
基本可以满足要求,力扣网上的一个长度为五万的测试用例超时了,需要进一步优化。
void quickSort(vector<int>& nums, auto it_left, auto it_right)
{
if(it_left<it_right){
auto left = it_left,right = it_right;
int jizhun = *it_left;
while(left<right){
while(left<right&&*right>=jizhun) right--;
if(left<right){
*(left++) = *right;
}
while(left<right&&*left<jizhun) left++;
if(left<right){
*(right--) = *left;
}
}
*left = jizhun;
quickSort(nums,it_left,left-1);
quickSort(nums,left+1,it_right);
}
}
优化写法,优化了循环结构,避免了交换操作,在一轮完成后直接将基准值赋值给左边界。同时函数为void类型比容器类型用时更少,若为容器类型,依然会超时。
另外,迭代器与下标哪个更快?似乎下标更快一些,这样vector的迭代器优点是什么?
void quickSort(vector<int>& nums,int left,int right) {
int it = left;
bool xunhuan = true;
while (xunhuan){
for(int r = right-1;r>=left;r--){
if (nums[r]<nums[it]){
swap(nums[r],nums[it]);
it = r;
break;
}
if(r==it){
xunhuan = false;
break;
}
}
for(int r = left;r<right;r++){
if (nums[r]>nums[it]){
swap(nums[r],nums[it]);
it = r;
break;
}
if(r==it){
xunhuan = false;
break;
}
}
}
if (it>left+1) {
quickSort(nums,left,it);
}
if (it<right-2) {
it++;
quickSort(nums,it,right);
}
}
之期超时的算法,重新写成下标形式,成功通过,但用时是优化后的20倍左右,可以看出算法结构的确存在问题,但迭代器与返回类型对于时间的影响超过之前的认知。
3.归并排序
归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
图片来源:https://www.cnblogs.com/chengxiao/p/6194356.html
class Solution {
public:
vector<int> sortArray(vector<int>& nums) {
return mergeSort(nums);
}
vector<int> mergeSort(vector<int> nums) {
if(nums.size()==0){
return {};
}
if(nums.size()==1){
return nums;
}
auto b = nums.begin(),e = nums.end();
vector<int> left = mergeSort(vector<int> (b,b+(e-b)/2));
vector<int> right = mergeSort(vector<int> (b+(e-b)/2,e));
auto l = left.begin(),r = right.begin();
vector<int> ans;
for(int i = 0;i<(left.size()+right.size());i++){
if (l != left.end()&&(r ==right.end()||*l < *r)){
ans.push_back(*l);
l++;
continue;
}
if(r !=right.end()&&(l ==left.end()||*l >=*r)){
ans.push_back(*r);
r++;
continue;
}
}
return ans;
}
};
注意归并排序时,递归后合并数组指针的处理,可能会产生溢出。