快排和归并排序讲解
快速排序
思路:找数组的最后一个数字,假设为number,然后number为标准,调整数组:数组左边是小于number的数,中间是等于number的数,右边是大于number的数,然后对小于number的部分继续进行上述操作,对大于number的部分继续进行上述操作。这是普通的快速排序,和数据的状态有关,最好的情况的时间复杂度是o(n*log^n)。最好情况:我们假设上述蓝字为操作一,当进行完操作一后,等于number的数正好在数组的最中间。最坏的情况的时间复杂度o(n^2。最坏情况:进行完操作一后等于number的数在数组的最左边或最右边。
由于这种弊端的存在,所有又发明了随机快排,随机快排和普通快排的唯一差别就是在选number的时候,普通快排是选择的数组的最后一个数,而随机快排是选择数组随机一个位置上的数。
普通快排代码:
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int a[100];
int i1;
int i2;
void dengyu(int i,int j,int number);
void swap(int i,int j)
{
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
void quicksort(int i,int j)
{
if(i>j||i==j)
{
cout<<'1'<<" "<<i<<" "<<j<<endl;
return ;
}
int number=a[j];
dengyu(i,j,number);
int b[2];//用一个数组保存好等于number区域的左边界和右边界的下标
b[0]=i1;
b[1]=i2;
quicksort(i,b[0]);
quicksort(b[1],j);
}
void dengyu(int i,int j,int number)//这个函数求的是等于number区域的左边界和右边界的下标
{
int less=i-1;
int more=j+1;
int cur=i;
while (cur<more)
{
if(a[cur]<number)
{
swap(cur,less+1);
cur++;
less++;
}
else if(a[cur]==number)
cur++;
else
{
swap(cur,more-1);
more--;
}
}
i1=less;
i2=more;
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
quicksort(0,n-1);
for(int i=0;i<n;i++)
cout<<a[i]<<" ";
}
归并排序
基本思想:
将数组从中间分开,对前一半进行排序,对后一半进行排序,然后将前后两部分合并,使数组整体有序。在对前一半和后一半进行排序时,还是用进行上述操作。
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n;
int a[100];
void hebing(int i,int mid,int j)
{
int help[j-i+1];
int u=0;
int p1=i;
int p2=mid+1;
while (p1<=mid&&p2<=j)
{
help[u++]=a[p1]<a[p2]?a[p1++]:a[p2++];
}
while (p1<=mid)
{
help[u++]=a[p1++];
}
while (p2<=j)
{
help[u++]=a[p2++];
}
for(int i1=0;i1<(j-i+1);i1++)
a[i+i1]=help[i1];
}
void guibing(int L,int R)
{
if(R==L)
return ;
int mid=(L+R)/2;
guibing(L,mid);
guibing(mid+1,R);
hebing(L,mid,R);
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
guibing(0,n-1);
for(int i=0;i<n;i++)
cout<<a[i]<<" ";
}