排序算法大总结(持续更新。。。)

                              想都是问题, 做才是答案 

 伴随着算法学习的深入见到的题目变多。 

发现自己越来越菜,越深感对基本算法的掌握很是薄弱,昨天补题,知道用二分,二分却打不出。。。白给!!!

这篇博客多总结一下各种排序算法,毕竟很多题也是用到了各种排序方法的思想。。。大部分代码均来自啊哈算法。。

快速排序:

主要思路:选择一个基准数字(一般是第一个数字),设置两个指针分别为 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;
}

插入排序

#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;
}

希尔排序 改进的插入排序

#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;
}
发布了51 篇原创文章 · 获赞 21 · 访问量 3084

猜你喜欢

转载自blog.csdn.net/qq_44115065/article/details/102862026