zoukankan      html  css  js  c++  java
  • 算法与数据结构5.2 Bubble Sort

    ★实验任务

    给定一个 1~N 的排列 P,即 1 到 N 中的每个数在 P 都只出现一次。 现在要 对排列 P 进行冒泡排序,代码如下:

    for (int i = 1; i <= N; ++i) 
        for (int j = N, t; j > i; ‐‐j) 
            if (P[j ‐ 1] > P[j]) 
            t = P[j], P[j] = P[j ‐ 1], P[j ‐ 1] = t; 
    

    在排序过程中,数字的位置可能会发生变化。对于 1~ N 的每个数字,你需 要输出过程中达到的最左位置下标和最右位置下标的差的绝对值。

    ★数据输入

    第一行为 N,表示排列长度。
    第二行为排列 P。
    数据保证:
    80%的数据,N <= 1000
    100%的数据,N <= 100000

    ★数据输出

    输出一行,第 i 个数字表示数字 i 最左与最右位置的差的绝对值。

    输入示例 输出示例
    4
    3 2 1 4
    2 1 2 0

    ★注释
    样例冒泡排序过程:
    swap 2 1: 3 2 1 4 > 3 1 2 4
    swap 3 1: 3 1 2 4 > 1 3 2 4
    swap 3 2: 1 3 2 4 > 1 2 3 4

    思路

    不难发现,对于一个数i,其运动轨迹是先向右移再向左移,原数组i右面有几个比他小的就右移多少格最左端由i原来的位置和最后的位置最小值决定。

    那么我们的主要目的就是求一个数后面有几个数比它小

    1.最普通的想法就是:每遇到一个数往后找它后面有几个数比它小。这个做法的时间复杂度是n*n,只能适用于规模比较小的数据。

    2.归并的想法:建立数组p,p[i]表示数字i后有几个数比它小。在归并的两段序列合并的时候,先令一个计数变量sum=0,扫描左右两段left[],和right[]数组合并时,如果左面的数left[i]比右面的数right[i]大,则p[left[i]]加上这个sum,弹出right[i];如果左面的数left[i]比右面的数right[i]小,则
    sum++,弹出left[i]。这样做的原因是左右连个数组已经是有序排列,如果left[i]后面有n个数比它小,则left[i+1]后面也一定至少有n个数比它小。

    Code

     
    #include<iostream>
    #include<string.h>
    using namespace std;
    int p[100001]={0},Left[100001]={0},Right[100001]={0};
    void merge(int *arr,int l,int mid,int r)
    {
    	int i,j,k;
    	for(i = l;i <= mid;i++)
    	{
    		Left[i] = arr[i];
    	}
    	for(j = mid+1;j <= r;j++)
    	{
    		Right[j] = arr[j];
    	}
    	i=l,j=mid+1,k=l;
    	int sum=0;
    	while((i<=mid)&&(j<=r))
    	{
    		if(Left[i]>Right[j])
    		{
    			sum++;
    			arr[k++]=Right[j++];
    		}
    		else
    		{
    			p[Left[i]]+=sum;
    			arr[k++]=Left[i++];
    		}
    	}
    	while(i <= mid)
    	{
    		arr[k++] = Left[i++];
    		p[Left[i-1]] += sum;
    	}
    	while(j <= r)
    	{
    		arr[k++] = Right[j++];
    	}
    }
    void mergesort(int *arr,int l,int r)
    {
    	int mid=(l+r)/2;
    	if(r<=l)return;
    	mergesort(arr,l,mid);
    	mergesort(arr,mid+1,r);
    	merge(arr,l,mid,r);
    }
    int min(int x,int y)
    {
    	if(x>y)return y;
    	else return x; 
    }
    int max(int x,int y)
    {
    	return x>y?x:y;
    }
    int main()
    {
    	int n,i;
    	int a[100001],b[100001];
    	memset(a,0,sizeof(a));
    	memset(b,0,sizeof(b));
    	scanf("%d",&n);
    	for(i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		b[a[i]]=i;
    	}
    	mergesort(a,1,n);
    //	for(i=1;i<=n;i++)
    //	{
    //		printf("%d ",p[i]);
    //	}
    //	printf("
    ");
    	for(i=1;i<=n;i++)
    	{
    		printf("%d ",b[i]+p[i]-min(b[i],i));
    	}
    	return 0;
    }
            
    
  • 相关阅读:
    EL表达式
    单例模式
    标准标签JSTL
    五大常用算法之三:贪心算法
    python字符串处理
    判断视图存不存在
    判断插入的数据在表中存不存在
    sql因为发现对象名称 'dbo.Ct2' 和索引名称 'PK_Ct2' 有重复的键,所以ALTER TABLE ALTER COLUMN 。。。 失败。
    C# MD5算法 16 32 大小写
    制作VS2022中文离线安装包
  • 原文地址:https://www.cnblogs.com/031602523liu/p/7740277.html
Copyright © 2011-2022 走看看