想都是问题, 做才是答案
伴随着算法学习的深入,见到的题目变多。
发现自己越来越菜,越深感对基本算法的掌握很是薄弱,昨天补题,知道用二分,二分却打不出。。。白给!!!
这篇博客多总结一下各种排序算法,毕竟很多题也是用到了各种排序方法的思想。。。大部分代码均来自啊哈算法。。
快速排序:
主要思路:选择一个基准数字(一般是第一个数字),设置两个指针分别为 i和j,j从序列后面往前跳动,i从序列前面往后跳动,j遇到一个比基准数字小的数字那么停止,i遇到一个比基准数字大的数字停止,如果i和j不相等,那么将这两个数字交换,直到i和j相等,终止循环,将第i个数字和选择的基准数字交换位置,那么操作之后i前面的数字就全都小于等于它,i后面的数字均大于等于它,那么就找到了这个基准数字应该在的位置,快速排序的每一次都可以说是为了找到这个基准数字应该在的位置。然后递归排序i前面的和i后面序列就可以了。快速排序的时间复杂度并不稳定,最差的情况下为O(N^2),平均时间复杂度为O(logN)。此外还有一点需要注意,那就是指针i和j哪一个先移动,基准值选择在左端的时候要右边的指针先移动,至于原因详https://blog.csdn.net/u013447565/article/details/82079959。
#include<iostream>
#include<algorithm>
using namespace std;
void quick_sort(int *a,int x,int y)
{
if(x>=y)
return;
int i=x,j=y;
int temp=a[x];
while(i!=j)
{
while(i<j&&a[j]>=temp)
j--;
while(i<j&&a[i]<=temp)
i++;
if(i!=j)
{
int t=a[i];
a[i]=a[j];
a[j]=t;
}
}
a[x]=a[i];
a[i]=temp;
quick_sort(a,x,i-1);
quick_sort(a,i+1,y);
}
int main()
{
freopen("in.txt","r",stdin);
int n,a[100000+10];
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
quick_sort(a,1,n);
for(int i=1;i<=n;i++)
{
cout<<a[i]<<" ";
}
return 0;
}
堆排序
堆的性质:
堆的形状根完全二叉树的形状一样,都是树的右下角缺少若干叶子结点。
小根堆:树的根结点为最小值,每个父结点都比他的两个子结点要小,堆一般采用数组存储,假设父结点在数组中的编号为i,那么他的左孩子的编号为2*i,右孩子为2*i+1,且父结点的值都比他的两个子结点值小,如果要往堆中添加一个值,那么只需在数组末尾添加,然后将这个数字移动到合适的位置即可,取最小元素的话,那么根节点就是最小元素,这时再添加元素只需要让数组第一个元素为新添加的元素,然后下放到合适的位置即可。在下放的时候要选择选择两个元素中更小那个元素位置进行交换。
具体排序方法
#include<iostream>
#include<algorithm>
using namespace std;
int n,a[100000+10];
void siftdown(int i)
{
int t,flag=0;
while(i*2<=n&&flag==0)
{
if(a[i]<a[i*2])
t=i*2;
else
t=i;
if(i*2+1<=n&&a[t]<a[i*2+1])
{
t=2*i+1;
}
if(t!=i)
{
swap(a[t],a[i]);
i=t;
}
else
flag=1;
}
}
void creat()
{
for(int i=n/2;i>=1;i--)
{
siftdown(i);
}
return;
}
void heapsort()
{
while(n>1)
{
swap(a[n],a[1]);
n--;
siftdown(1);
}
return;
}
int main()
{
cin>>n;
int temp=n;
for(int i=1;i<=n;i++)
cin>>a[i];
creat();
heapsort();
for(int i=1;i<=temp;i++)
cout<<a[i]<<" ";
return 0;
}
归并排序:
主要就是分治思想
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn=100000+10;
const int inf=0x7f7f7f7f;
int L[maxn],R[maxn],a[maxn];
int cnt=0; // 执行了多少次比较运算
void merge(int *a,int n,int Left,int mid,int Right)
{
int n1=mid-Left+1;
int n2=Right-mid;
for(int i=1;i<=n1;i++)
{
L[i]=a[Left+i-1];
}
for(int i=1;i<=n2;i++)
{
R[i]=a[mid+i];
}
L[n1+1]=inf;
R[n2+1]=inf;
int i=1;
int j=1;
for(int p=Left;p<=Right;p++)
{
cnt++;
if(L[i]<=R[j])
{
a[p]=L[i++];
}
else
{
a[p]=R[j++];
}
}
}
void mergesort(int *a,int n,int L,int R)
{
if(R-L>=1)
{
int mid=(L+R)>>1;
mergesort(a,n,L,mid);
mergesort(a,n,mid+1,R);
merge(a,n,L,mid,R);
}
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("in.txt","r",stdin);
#endif
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
mergesort(a,n,1,n);
for(int i=1;i<=n;i++)
{
printf("%d ",a[i]);
}
return 0;
}
归并排序求逆序对
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn = 500000 + 10;
const int inf = 0x7f7f7f7f;
int L[maxn], R[maxn], a[maxn];
ll merge(int *a, int n, int Left, int mid, int Right)
{
ll cnt = 0;
int n1 = mid - Left + 1;
int n2 = Right - mid;
for (int i = 1; i <= n1; i++)
{
L[i] = a[Left + i - 1];
}
for (int i = 1; i <= n2; i++)
{
R[i] = a[mid + i];
}
L[n1 + 1] = inf;
R[n2 + 1] = inf;
int i = 1;
int j = 1;
for (int p = Left; p <= Right; p++)
{
if (L[i] <= R[j])
{
a[p] = L[i++];
}
else
{
a[p] = R[j++];
cnt += (n1 - i + 1);
}
}
return cnt;
}
ll mergesort(int *a, int n, int L, int R)
{
if (R - L >= 1)
{
int mid = (L + R) >> 1;
ll v1 = mergesort(a, n, L, mid);
ll v2 = mergesort(a, n, mid + 1, R);
ll v3 = merge(a, n, L, mid, R);
return v1 + v2 + v3;
}
else
return 0;
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("in.txt", "r", stdin);
#endif
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
cout << mergesort(a, n, 1, n) << endl;
for (int i = 1; i <= n; i++)
{
printf("%d ", a[i]);
}
return 0;
}
计数排序
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100000 + 10;
const int max_val = 1000000 + 10;
int n, A[maxn], B[maxn], C[max_val];
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("in.txt","r",stdin);
#endif
memset(C, 0, sizeof C);
memset(B, 0, sizeof B);
cin >> n;
for (int i = 1; i <= n;i++)
{
cin >> A[i];
C[A[i]]++;
}
for (int i = 1; i <= max_val+3;i++)
C[i]=C[i]+C[i-1];
for (int j = n; j >= 1;j--)
{
B[C[A[j]]] = A[j];
C[A[j]]--;
}
for (int i = 1; i <= n; i++)
cout << B[i] << " ";
return 0;
}
冒泡排序
#include<iostream>
#include<algorithm>
using namespace std;
void bubble_sort(int *a,int n)
{
bool flag = 1;
for (int i = 1; flag;i++)
{
flag = 0;
for (int j = n; j >= i + 1;j--)
{
if(a[j]<a[j-1])
{
swap(a[j], a[j - 1]);
flag = 1;
}
}
}
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("in.txt","r",stdin);
#endif
int n, a[100000+10];
cin >> n;
for (int i = 1; i <= n;i++)
cin >> a[i];
bubble_sort(a, n);
for (int i = 1; i <= n;i++)
cout<<a[i]<<" ";
return 0;
}
选择排序
#include<iostream>
#include<algorithm>
using namespace std;
void select_sort(int *a,int n)
{
for (int i = 1; i <= n;i++)
{
int minj = i;
for (int j = i; j <= n;j++)
{
if(a[j]<a[minj])
minj = j;
}
swap(a[i], a[minj]);
}
}
int main()
{
freopen("in.txt","r",stdin);
int n, a[1000];
cin >> n;
for (int i = 1; i <= n;i++)
cin >> a[i];
select_sort(a, n);
for (int i = 1; i <= n;i++)
cout<<a[i]<<" ";
return 0;
}
插入排序
void insert_sort(int a[], int n)
{
for (int i = 1; i < n; i++)
{
int v = a[i];
int j = i - 1;
while (j >= 0 && a[j] > v)
{
a[j + 1] = a[j];
j--;
}
a[j + 1] = v;
}
}
int main()
{
#ifdef WXY
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
IO;
int n;
int a[100];
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
insert_sort(a, n);
for (int i = 0; i < n; i++)
cout << a[i] << " ";
return 0;
}
希尔排序 改进的插入排序
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 1e6 + 10;
int n, cnt, a[maxn];
vector<int> G;
void insert_sort(int *a, int n, int g)
{
for (int i = g + 1; i <= n; i++)
{
int v = a[i];
int j = i - g;
while (j >= 1 && a[j] > v)
{
a[j + g] = a[j];
j -= g;
cnt++;
}
a[j + g] = v;
}
}
void shell_sort(int *a, int n)
{
for (int h = 1;;)
{
if (h > n)
break;
G.push_back(h);
h = 3 * h + 1;
}
for (int i = G.size() - 1; i >= 0; i--)
{
insert_sort(a, n, G[i]);
}
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("in.txt", "r", stdin);
#endif
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
cnt = 0;
shell_sort(a, n);
for (int i = 1; i <= n; i++)
{
cout << a[i] << " ";
}
return 0;
}