牛客字节跳动高频题:排序算法
在此总结下排序算法的基本概念,代码亲自码一遍。
术语说明
1、稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 仍然在 b 的前面,则为稳定排序。
2、非稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 可能不在 b 的前面,则为非稳定排序。
3、原地排序:原地排序指在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序。
4、非原地排序:需要利用额外的数组来辅助排序。
5、时间复杂度:一个算法执行所消耗的时间。
6、空间复杂度:运行完一个算法所需的内存大小。
一、冒泡排序
//冒泡排序,超时
vector<int> MySort(vector<int>& arr) {
int n=arr.size();
for(int i=n-1;i>=0;i--){
for(int j=1;j<i+1;j++){
if(arr[j]<arr[j-1]){
int temp=arr[j];
arr[j]=arr[j-1];
arr[j-1]=temp;
}
}
}
return arr;
}
二、选择排序
vector<int> MySort(vector<int>& arr) {
// write code here
int n=arr.size();
//选择排序,超时
for(int i=0;i<n;i++){
int k=i;
for(int j=i+1;j<n;j++){
if(arr[k]>arr[j]){
k=j;
}
}
if(k!=i){
int temp=arr[k];
arr[k]=arr[i];
arr[i]=temp;
}
}
return arr;
}
三、插入排序
vector<int> MySort(vector<int>& arr) {
// write code here
int n=arr.size();
//插入排序,超时
for(int i=1;i<n;i++){
int temp=arr[i];
int j=i;
while(j>=1&&temp<arr[j-1]){
arr[j]=arr[j-1];
j--;
}
arr[j]=temp;
}
return arr;
}
四、归并排序
归并递归排序:
vector<int> MySort(vector<int>& arr) {
// write code here
int n=arr.size();
//二分法递归
helper(arr,0,n-1);
return arr;
}
//二分法递归辅助函数
void helper(vector<int> &arr,int left,int right){
vector<int> res;
if(left<right){
int mid=left+(right-left)/2;
helper(arr,left,mid);
helper(arr,mid+1,right);
int i=left;
int j=mid+1;
while(i<=mid&&j<=right){
if(arr[i]<=arr[j]){
res.push_back(arr[i]);
i++;
}
else {
res.push_back(arr[j]);
j++;
}
}
while(i<=mid){
res.push_back(arr[i]);
i++;
}
while(j<=right){
res.push_back(arr[j]);
j++;
}
}
for(int i=0;i<res.size();i++){
arr[left+i]=res[i];
}
}
归并非递归排序:
vector<int> MySort(vector<int>& arr) {
// write code here
int n=arr.size();
//二分法非递归
for(int step=2;step/2<n;step*=2){
for(int i=0;i<n;i+=step){
int mid=i+step/2-1;
if(mid+1<n){
merge(arr,i,mid,mid+1,min(i+step-1,n-1));
}
}
}
return arr;
}
//二分法非递归辅助函数
void merge(vector<int> &arr,int al,int ar,int bl,int br){
vector<int> res;
int i=al;
int j=bl;
while(i<=ar&&j<=br){
if(arr[i]<=arr[j]){
res.push_back(arr[i++]);
}
else{
res.push_back(arr[j++]);
}
}
while(i<=ar){
res.push_back(arr[i++]);
}
while(j<br){
res.push_back(arr[j++]);
}
for(int k=0;k<res.size();k++){
arr[al+k]=res[k];
}
}
五、快速排序
vector<int> MySort(vector<int>& arr) {
// write code here
int n=arr.size();
//快速排序
quick(arr,0,n-1);
return arr;
}
//快速排序主函数
void quick(vector<int> &arr,int left,int right){
if(left<right){
int k=partion(arr,left, right);//此函数已经对数组进行划分,并找到划分节点位置
quick(arr,left,k-1);
quick(arr,k+1,right);
}
}
//快速排序划分函数,返回该节点的排序位置
int partion(vector<int> &arr,int left,int right){
int temp=arr[left];
while(left<right){
while(left<right&&arr[right]>=temp){//注意这里要有等于号,表示一直要找到比temp小的数
right--;
}
arr[left]=arr[right];
while(left<right&&arr[left]<=temp){
left++;
}
arr[right]=arr[left];
}
arr[left]=temp;
return left;
}