B1035 插入与归并思路(代码+详解)

题目
在这里插入图片描述

思路:

乙级的题目不会直接考数据结构,对于几种排序算法也不会直接让你求。
本题考的插入和归并排序,其实不用完全掌握并写出代码也能做(能掌握当然好了)。只要理解了插入排序和归并排序的思路即可。 不行,还是得会,不然求不了归并的下一轮。

插入排序:将数组的第一个数认为是有序数组,把数组中其余n-1个数,插入到有序数组中,直至数组中的所有数有序排列为止。
对本题而言,插入排序过程中的前某m项是有序的。(从题目来看是从后往前扫描)

		代码实现从小到大排序:
		#include<stdio.h>
		  void InsertionSort(int *num,int n) 
		  {
		  	int i = 0;
		  	int j = 0;
		  	int tmp = 0;
		  	for(i = 1;i<n;i++)//n个数要进行n-1趟
		  	{
		          tmp = num[i];//从待插入组取出第一个元素。 
			  j = i-1; //i-1即为有序组最后一个元素(与待插入元素相邻)的下标 ,开始时j=i-1=0。
			  while(j>=0&&tmp<num[j])  //注意判断条件为两个,j>=0对其进行边界限制。第二个为插入判断条件 
			  {
			    num[j+1] = num[j];//若不是合适位置,有序组元素向后移动 
				j--; 
			  }
			  num[j+1] = tmp;//找到合适位置,将元素插入。 
			}
		  }
		  int main() 
		  {
		  	int i = 0;
		  	int num[8]={9,3,4,2,6,7,5,1};
		  	InsertionSort(num,8); 
		  	for(i=0;i<8;i++)
		  	{
		     	printf("%d ",num[i]);
			}
		  	return 0;
		  }

归并排序
归并排序有两种思路
1. 自顶向下(Top-Down)
直接在原序列上直接归并排序,每次归并排序分别对左右两边进行归并排序,直至细分到两两分组。
2.自底向上(Bottom-Up)
假设序列共有 n 个元素:
1. 先相邻两两分组进行归并排序
2. 再相邻四四分组进行归并排序
3. 再相邻八八分组进行归并排序
4. 重复扩大分组规模,直到所有元素排序完毕
5. …
对本题而言,显然采用的是第二种,自底向上,先两两分组排序。
代码出处:https://blog.csdn.net/Silence_R/article/details/86524975

#include<stdio.h>

/*归并排序*/
void Merge_Sort(int *arr, int *temparr,int start,int mid,int end)
{
    int left_start = start ;
    int left_end   = mid ;

    int right_start = mid+1 ;
    int right_end   = end ;

    int index = start ;

    while(left_start<=left_end&&right_start<=right_end)
    {
        if(arr[left_start]>arr[right_start])
            temparr[index++] = arr[right_start++] ;
        else
            temparr[index++] = arr[left_start++] ;
    }

    while(left_start<=left_end)
        temparr[index++] = arr[left_start++] ;

    while(right_start<=right_end)
        temparr[index++] = arr[right_start++] ;

    for(index = start ;index<=end ;++index)
        arr[index] = temparr[index] ;
}
void Sort_Message(int *arr, int *temparr,int start,int end)
{
    if(start<end)
    {
        int mid = (start+end)/2 ;
        Sort_Message(arr,temparr,start,mid) ;
        Sort_Message(arr,temparr,mid+1,end) ;
        Merge_Sort(arr,temparr,start,mid,end) ;
    }
}

int main(void)
{
    int a[] = {9,2,5,3,7,4,8,0} ;
    int n = sizeof(a)/sizeof(a[0]) ;
    int i, temp[8] ;

    printf("原序列为:") ;
    for(i=0;i<n;++i)
        printf("%d ",a[i]) ;
    printf("\n") ;

    Sort_Message(a,temp,0,n-1) ;

    printf("\n排后序列:") ;
    for(i=0;i<n;++i)
        printf("%d ",a[i]) ;
    printf("\n") ;
    return 0 ;
}


理解了两种排序方式后,本题的要求其实就很明显了:
给出原数组,判断前n个数是否有序——插入排序;else——归并排序。

或者:
判断是否所以数组两两有序或四四有序——归并排序;else——插入排序。
再进行求排序的下一轮:
对于插入排序,直接sort到有序位的下一位。
对于归并排序,求一遍归并排序。

AC代码

#include <iostream>
#include <algorithm>
using namespace std;
int main(){
	int n, a[100], b[100], i, j;
	cin >> n;
	for(int i = 0; i < n; i++)//原数组 
		cin >> a[i];
	for(int i = 0; i < n; i++)//排序数组 
		cin >> b[i];
		
	for(i = 0; i < n - 1 && b[i] <= b[i + 1]; i++);//判断插入排序:前i个有序,当发现无序时跳出循环 
	for(j = i + 1; a[j] == b[j] && j < n; j++);  
	if(j == n){                                //上面循环遍历后,如果j==n,说明前 i个有序,后i+1到n-1个未排序。很明显为插入排序。 
		cout << "Insertion Sort" << endl;     
		sort(a, a + i + 2);                   //插入排序再迭代一轮,就是将第i+1个也排序进去。 a[i+1]在sort函数中地址是a+i+2 
	} 
	
	 
	else{                                   //反之则为归并排序 
		cout << "Merge Sort" << endl;         //输出再排序一轮的数组 
		int k = 1, flag = 1;                  // 
		while(flag){
			flag = 0;
			for(int i = 0; i < n; i++){       //对数组a遍历,只要有和b数组不一样的就继续。 
				if(a[i] != b[i])              //如果两数组一样,说明到了题目给出的那轮。跳出循环。 
					flag = 1;
			}
			k = k * 2;                         //k = 2 4 8...n。从两两一组开始,每组排序。 
			for(int i = 0; i < n / k; i++)    //划分 n / k个组,对每个组内进行排序。
				sort(a + i * k, a + (i + 1) * k);
			sort(a + n / k * k, a + n);    //对序列最后不足一组的元素排序。
		}
	}
	for(j = 0; j < n; j++){
		if(j != 0) printf(" ");
		printf("%d", a[j]);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值