排序算法一览

排序算法一览

总览
排序算法 时间复杂度 空间复杂度 稳定性 原地排序?
冒泡排序 稳定
选择排序 不稳定
插入排序 稳定
希尔排序 不稳定
快速排序 不稳定
归并排序 稳定
基数排序 稳定
堆排序 O(nlogn) O(1) 不稳定
冒泡排序
/**
 * @brief 冒泡排序
 * 时间复杂度 O(n^2)
 * 空间复杂度 O(1)
 * 原地排序 稳定
 * 
 * @param nums 
 */
void bubbleSort(vector<int>& nums){
    int n=nums.size();
    for(int i=0;i<n-1;++i){
        for(int j=0;j<n-i-1;++j){
            if(nums[j]>nums[j+1]){
                int t=nums[j];
                nums[j]=nums[j+1];
                nums[j+1]=t;
            }
        }
    }
}
/*优化*/
void bubbleSort(vector<int>& nums){
    int n=nums.size();
    for(int i=0;i<n-1;++i){
        int flag=1;                //标记位,为1表示已经有序,为0表示尚未有序
        for(int j=0;j<n-i-1;++j){
            if(nums[j]>nums[j+1]){
                int t=nums[j];
                nums[j]=nums[j+1];
                nums[j+1]=t;
                flag=0;
            }
        }
        if(flag) break;
    }
}
选择排序
/**
 * @brief 选择排序
 * 时间复杂度 O(n^2)
 * 空间复杂度 O(1)
 * 原地排序 不稳定(会将重复的后面的较小值交换到前面来)
 * @param nums 
 */
void selectSort(vector<int>& nums){
    int n=nums.size();
    for(int i=0;i<n-1;++i){
        int mini=i;
        for(int j=i+1;j<n;++j){
            if(nums[mini]>nums[j]){
                mini=j;
            }
        }
        if(mini!=i){
            int t=nums[mini];
            nums[mini]=nums[i];
            nums[i]=t;
        }
    }
}
插入排序
/**
 * @brief 插入排序
 * 时间复杂度 O(n^2)
 * 空间复杂度 O(1);
 * 原地排序 稳定
 * 
 * @param nums 
 */
void insertSort(vector<int>& nums){
    int n=nums.size();
    for(int i=1;i<n;++i){
        if(nums[i]<nums[i-1]){
            int temp=nums[i];
            int j;
            for(j=i;nums[j-1]>temp&&j>0;--j){
                nums[j]=nums[j-1];
            }
            nums[j]=temp;
        }
    }
}
希尔排序
/**
 * @brief 希尔排序
 *时间复杂度  O(nlogn) 最坏 O(n^s)
 *空间复杂度 O(1)
 *原地排序 不稳定
 * @param nums 
 */
void sheelSort(vector<int> &nums){
    int n=nums.size();
    int gap=1,i,j;
    while(gap<n/3){
        gap=3*gap+1;
    }
    while(gap>=1){
        for(i=gap;i<n;i++){
            if(nums[i]<nums[i-gap]){
                int temp=nums[i];
                for( j=i-gap;j>=0&&nums[j]>temp;j-=gap){
                    nums[j+gap]=nums[j];
                }
                nums[j+gap]=temp;
            }
        }
        gap=gap/3;

    }
}
快速排序
/**
 * @brief 快速排序
 * 时间复杂度 O(nlogn); 最坏O(n^2)
 * 空间复杂度 O(logn)
 * 原地排序,不稳定
 */
void quickSort(vector<int>& nums,int left,int right){
    if(left>=right){
        return;
    }
    int temp=nums[left];
    int i=left,j=right;
    while(i!=j){
        while(nums[j]>=temp&&i<j){
            --j;
        }
        while(nums[i]<=temp&&i<j){ //i及左侧必然小于等于temp
            ++i;
        }
        if(i<j){
            int t=nums[i];
            nums[i]=nums[j];
            nums[j]=t;
        }
    }
    nums[left]=nums[i];
    nums[i]=temp;
    quickSort(nums,left,i-1);
    quickSort(nums,i+1,right);
}

void quickSortP(vector<int>& nums,int left,int right){
    if(left>=right){
        return;
    }
    int temp=nums[left];
    int i=left,j=right;
    while(i<j){
        while(nums[j]>=temp&&i<j){
            --j;
        }
        while(nums[i]<=temp&&i<j){ //i及左侧必然小于等于temp
            ++i;
        }
        if(i<j){
            int t=nums[i];
            nums[i]=nums[j];
            nums[j]=t;
        }
    }
    nums[left]=nums[i];
    nums[i]=temp;
    quickSortP(nums,left,i-1);
    quickSortP(nums,i+1,right);
}
归并排序
/**
 * @brief 归并排序
 * 时间复杂度 O(nlogn)
 * 空间复杂度 O(n)
 * 非原地排序 稳定
 * 
 * @param nums 
 */
//递归计算
void mergeSort(vector<int>& nums,int left,int right){
    if(left>=right){
        return;
    }
    int mid=(left+right)/2;
    mergeSort(nums,left,mid);
    mergeSort(nums,mid+1,right);

    vector<int> temp(right-left+1);
    int i=left,j=mid+1,k=0;
    while(i<=mid||j<=right){
        if(i>mid){
            temp[k++]=nums[j++];
        }
        else if(j>right){
            temp[k++]=nums[i++];
        }
        else{
            if(nums[i]<=nums[j]){
                temp[k++]=nums[i++];
            }
            else{
                temp[k++]=nums[j++];
            }
        }
    }
    for(int t=0;t<temp.size();++t){
        nums[left+t]=temp[t];
    }
}
//迭代计算
void mergeSortD(vector<int>& nums){
    int n=nums.size();
    int left,right;
    vector<int> temp(n,0);
    for(int i=2;i<n;i*=2){
        for(left=0;left<n-i;left+=i){
            right=left+i-1;
            if(right>=n) right=n-1;
            int mid=(left+right)/2;
            int l=left,r=mid+1,k=0;
            while(l<=mid||r<=right){
                if(l>mid){
                    temp[k++]=nums[r++];
                }
                else if(r>right){
                    temp[k++]=nums[l++];
                }
                else{
                    if(nums[l]<=nums[r]){
                        temp[k++]=nums[l++];
                    }
                    else{
                        temp[k++]=nums[r++];
                    }
                }
            }
            for(k=0;k<right-left+1;++k){
                nums[left+k]=temp[k];
            }
        }
    }
    return;
}
基数排序
/**
 * @brief 基数排序
 * 
 */
void lsdSort(vector<int>& nums){
    int n=nums.size();
    int digit=0;
    for(int i=0;i<n;++i){
        while(nums[i]>(pow(10,digit))){
            digit++;
        }
    }
    int flag=1;
    for(int j=1;j<=digit;++j){
        vector<int> count(10);
        for(int i=0;i<n;++i){
           count[(nums[i]/flag)%10]++;
        }
        vector<int> index(10);
        for(int i=1;i<10;++i){
            index[i]=index[i-1]+count[i-1];
        }

        vector<int> temp(n);
        for(int i=0;i<n;++i){
            int begin=(nums[i]/flag)%10;
            temp[index[begin]++]=nums[i];
        }
        for(int i=0;i<n;++i){
            nums[i]=temp[i];
        }
        flag*=10;
    }
}
堆排序
/**
 * @brief 堆排序
 * 
 * @param s 
 * @param nums 
 */
void heapSort(vector<int> &nums){
    int n=nums.size();
    auto swap=[](int &a,int &b){
        int t=a;
        a=b;
        b=t;
    };
    auto sink=[&](int s,int len){
        int temp=nums[s-1];
        for(int i=2*s;i<=len;i*=2){
            if(i<len&&nums[i-1]<nums[i]){
                i++;
            }
            if(temp>=nums[i-1]){
                break;
            }
            nums[s-1]=nums[i-1];
            s=i;
        }
        nums[s-1]=temp;
    };
    for(int i=n/2;i>0;i--){ //从下向上,从右向左调整
        sink(i,n);
    }
    for(int i=n;i>1;--i){
        swap(nums[0],nums[i-1]);
        sink(1,i-1);  
    }
}
全部评论

相关推荐

整顿职场的柯基很威猛:这种不可怕,最可怕的是夹在一帮名校里的二本选手,人家才是最稳的。
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务