• Insert or Merge


    • 题目描述

    • 题目思路

    1 第一步是如何区分插入排序和归并排序,插入排序前面一部分是有序的,后面一部分尚未处理的序列没有变化。

    2 继续迭代
    (1) 插入排序的继续迭代比较好实现,只要从无序部分的第一个元素开始执行一次循环即可。
    (2) 归并排序的难点在于找到归并段,在找到正确的归并段后,将非递归的归并排序执行一趟即可。
    判断归并段长度的代码如下:

    //计算归并段的长度并返回归并段长度
    int MergeLength(int *B,int N)
    {
    	int l = 0;
    	int i = 0;
    	for (l = 2;l <= N;l = l * 2)
    	{
    		for (i = l;i < N;i = i + l * 2)
    		{
    			if (B[i] < B[i-1])
    			{
    				break;
    			}
    		}
    		if (i < N)
    		{
    			break;
    		}
    	}
    	return l;
    }
    

    • C语言实现
    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<stdlib.h>
    
    int IsInsertion(int *A,int *B,int N)
    {
    	int i, k;
    	for (i = 1;i < N;i++)
    	{
    		if (B[i] < B[i-1])
    		{
    			break;  //发现顺序不对 跳出循环
    		}
    	}
    	k = i;  //保存跳出点 为下一次进行插入排序做准备
    	for (;i < N;i++)
    	{
    		if (A[i] != B[i])
    		{
    			break;  //后面的序列有变化 说明不是插入排序 而是归并排序
    		}
    	}
    	if (i == N)
    	{
    		return k;  //是插入排序 返回插入的位置
    	}
    	else
    	{
    		return 0;  //不是插入排序
    	}
    }
    
    void PrintResults(int *B,int N)
    {
    	for (int i = 0;i < N - 1;i++)
    	{
    		printf("%d ",B[i]);
    	}
    	printf("%d", B[N-1]);
    }
    
    void NextInsertion(int *B,int N,int K)
    {
    	int tmp;
    	int i = 0;
    	printf("Insertion Sort
    ");
    	
    	tmp = B[K];
    
    	for (i = K-1;i >= 0;i--)
    	{
    		if (tmp < B[i])
    		{
    			B[i + 1] = B[i];
    		}
    		else
    		{
    			break;
    		}
    	}
    	B[i + 1] = tmp;
    	PrintResults(B,N);
    }
    //计算归并段的长度并返回归并段长度
    int MergeLength(int *B,int N)
    {
    	int l = 0;
    	int i = 0;
    	for (l = 2;l <= N;l = l * 2)
    	{
    		for (i = l;i < N;i = i + l * 2)
    		{
    			if (B[i] < B[i-1])
    			{
    				break;
    			}
    		}
    		if (i < N)
    		{
    			break;
    		}
    	}
    	return l;
    }
    
    void NextMerge(int *B,int N)
    {
    	int p1, p2;
    	int i;
    	int p;
    	int L;  //当前归并段的长度
    	int *Tmp;
    	printf("Merge Sort
    ");
    	L = MergeLength(B,N);
    
    	Tmp = (int *)malloc(sizeof(int) * N);
    	p = 0;  //p指向Tmp中当前处理的位置
    	
    	for (i = 0;i < (N-L-L);i = i + L + L)  //两两归并长度为L的段
    	{
    		p1 = i;
    		p2 = i + L;  //p1和p2分别指向两个段的当前处理位置
    		while ((p1 < (i + L)) && (p2 < (i + L + L)))
    		{
    			if (B[p1] > B[p2])
    			{
    				Tmp[p++] = B[p2++];
    			}
    			else
    			{
    				Tmp[p++] = B[p1++];
    			}
    		}  //end while ((p1 < (i + L)) && (p2 < (i + L + L)))
    		while (p1 < (i + L))
    		{
    			Tmp[p++] = B[p1++];
    		}
    		while (p2 < (i + L + L))
    		{
    			Tmp[p++] = B[p2++];
    		}
    	}
    	
    	if ((N-i) > L)
    	{
    		p1 = i;
    		p2 = i + L;
    		while ((p1 < (i+L)) && (p2 < N))
    		{
    			if (B[p1] > B[p2])
    			{
    				Tmp[p++] = B[p2++];
    			}
    			else
    			{
    				Tmp[p++] = B[p1++];
    			}
    		}
    		while (p1 < (i + L))
    		{
    			Tmp[p++] = B[p1++];
    		}
    		while (p2 < (i + L + L))
    		{
    			Tmp[p++] = B[p2++];
    		}
    	}
    	else
    	{
    		while (i < N)
    		{
    			Tmp[i] = B[i++];
    		}
    	}
    
    	PrintResults(Tmp,N);
    }
    
    int main()
    {
    	int *A;
    	int *B;
    	int N;
    	int k;
    	scanf("%d",&N);
    	A = (int *)malloc(sizeof(int) * N);
    	B = (int *)malloc(sizeof(int) * N);
    	
    	for (int i = 0;i < N;i++)
    	{
    		scanf("%d",&A[i]);
    	}
    
    	for (int i = 0; i < N; i++)
    	{
    		scanf("%d", &B[i]);
    	}
    
    	if (k = IsInsertion(A,B,N))
    	{
    		NextInsertion(B,N,k);
    	}
    	else
    	{
    		NextMerge(B,N);
    	}
    	// system("pause");
    	return 0;
    }
    
  • 相关阅读:
    两种方法实现超出省略号效果
    CSS中定义优先权
    网页设计中字体设置详解
    JavaScript的方法和技巧
    手把手教你使用Gene6FTP远程管理
    用Zend Encoder加密PHP文件和PHP 优化配置
    JavaScript的方法和技巧
    SQL Server 2000订阅与发布的具体操作
    企业级邮件服务软件推荐
    用Zend Encoder加密PHP文件和PHP 优化配置
  • 原文地址:https://www.cnblogs.com/Manual-Linux/p/11444837.html
Copyright © 2020-2023  润新知