事情是这样的,上周因为得了甲流,导致了没去上算法课。
然后今天听说算法课留了作业(简直匪夷所思)
然后题目是:
给定一个数组,输出最小的两个数字。
我:这不秒杀?直接一个sort排序,再将前两个数给输出不就完了?
后来听说这个还需要用到分治的思想
啊,这得好好想想,想了好一会才想到用快速排序和归并排序???
(果然API函数越用越蠢,但是用的是真的爽啊!!!!)
既然这样咱就趁这次抄一下手写一次快速排序和归并排序
快速排序:
#include<iostream>
using namespace std;
const int N=1e5+10;
int arr[N];
void quick_sort(int l,int r)
{
if(l>=r)return ;
int i=l, j=r, x=arr[i];
while(i<j) {
while (i<j && arr[j]>x) {j--;} // 从右向左找第一个小于x的数
if (i < j) {arr[i++] = arr[j];}// 将小于x的值放在左边
while (i < j && arr[i] < x) {i++;}// 从左向右找第一个大于x的数
if (i < j) {arr[j--] = arr[i];}// 将大于x的值放在右边
}
arr[i] = x;
quick_sort(l, i - 1);
quick_sort(i+1, r);
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;++i)
cin>>arr[i];
quick_sort(0,n-1);
cout<<arr[0]<<" "<<arr[1]<<endl;
return 0;
}
关于快速排序的算法,我们这里有几个细节
首先就是我们需要首先从右向左找小于x的值,再从左向右找第一个大于x的值
这个顺序不能换,至于为啥不能换,可以去模拟一下(由于这里只是记录一下作业,所以就不到此证明了)
其次就是这个递归的,不用递归第i个,因为第i个以及到了它该到的位置,所以就是:
quick_sort(l, i - 1);
和quick_sort(i+1, r);
归并排序:
#include<iostream>
using namespace std;
long long res=0;
const int N=100000+10;
int a[N],temp[N];
void merge_sort(int a[],int l,int r)
{
if(l>=r)return ;
int mid=l+r>>1;
merge_sort(a,l,mid);
merge_sort(a,mid+1,r);
int i = l, j = mid + 1,k = 0;
while(i<=mid&&j<=r)
{
if(a[i]<=a[j]) temp[k++]=a[i++];
else temp[k++]=a[j++];
}
while(i<=mid) temp[k++]=a[i++];
while(j<=r) temp[k++]=a[j++];
for(int i=l,j=0;i<=r;++i,++j) a[i]=temp[j];
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;++i)cin>>a[i];
merge_sort(a,0,n-1);
cout<<a[0]<<" "<<a[1]<<endl;
return 0;
}
归并排序也是一个典型的分治的排序算法
它这个思想就是创建一个数组和一个临时数组,
接下来将整个数组不断的分成一半一半,最后分到一个数组只有两个,再将两个进行排序
接着再将两个已经排好序的数组再合并一下,合并的临时数组里面。
最后将临时数组赋值到实际的数组里面
最后讲个小故事(我也忘记从哪里听来的)
据说以前人们研究排序算法,一直无法突破O(n^2),所以科学家们一直
以为排序算法的极限就是O(n^2)了,直到后来有个人发现了这个分而治之
的算法,也就发明了快速排序算法(好像是这个),后来就有不少人利用
类似的思想,最后就出现了好几种复杂度为O(nlogn)的算法。
那就记录到这里吧。
end---