IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> [PAT练级笔记] 35 Basic Level 1035 插入与归并 -> 正文阅读

[数据结构与算法][PAT练级笔记] 35 Basic Level 1035 插入与归并

乙级的题目训练主要用来熟悉编程语言的语法和形成良好的编码习惯和编码规范。从小白开始逐步掌握用编程解决问题。

PAT乙级BasicLevelPractice 1035

问题分析

题设给定两组数, 第二组数是第一组数用插入排序或归并排序进行排序的某个中间状态,
要求判断使用的是哪种排序, 并用这种排序算法对排序的中间状态再排序一次并输出.

从题设中我们识别到两个功能需求:
- 判断所使用的排序算法
- 使用对应排序算法再进行一次排序

如果区分插入排序和归并排序

根据插入排序的特征, 排序过程中数组左半部分为排序部分, 右半部分为未排序部分.
而归并排序会同时变动整个数组.
题设保证了每组测试结果唯一, 所以不用担心出现插入排序和归并排序中间状态一致的情况.

我们只需要检查排序中间状态的数组是否符合"左边最长有序部分之外的另一部分是否是未排序部分(即与原数组对应部分完全西昂同)"
即, 检查第二个序列升序部分的末尾索引, 然后从该位置开始检查直到数组末尾是否都和原数组一致

得到插入排序的下一个结果

插入排序第n次的结果和第n+1次的结果, 差别在于: 左边有序部分的长度.
所以我们只需要对左起的n个元素进行排序, 其余部分不变, 排序的结果就是插入排序n次后的结果.

得到归并排序的下一个结果

归并排序第n次的结果和第n+1次的结果, 差别在于: 有序区块的长度.
比如对于数列 [3, 1, 2, 8, 7, 5, 9, 4, 6, 0]
第1次排序是以区块长度为1, 即 对[3], [1], [2], [8], [7], [5], [9], [4], [6], [0]的排序结果
第2次排序是以区块长度为2, 即 对[3, 1], [2, 8], [7, 5], [9, 4], [6, 0]的排序结果.
所以要得到第n次归并排序的结果, 我们只需要对每个长度为n的子数组进行排序, 末尾不足n的部分单独排序即可得到预期结果

完整描述步骤

  1. 获取两组数列
  2. 计算第二组数列从左起开始有序部分的末尾索引 k,
    检查从有序部分末尾索引开始直到整个数组结束, 是否每个值都跟原数组一致.
    如果一致, 说明右边部分没有被排序过, 则为 插入排序
    否则, 为归并排序
  3. 如果是插入排序, 则将前k+1个元素进行排序(k为当前左边有序部分的长度)
    如果是归并排序, 则以k2为区块长度, 从左往右对每个区块进行排序. 末尾不足k2的部分也要单独排序

伪代码描述

  1. get input of two array:

    • numbers_amount
    • numbers
    • numbers_sorted_partially
  2. set current_sorted_amount = 1, sorting_method = InsertionSort;

  3. for (; current_sorted_amount < numbers_amount; current_sorted_amount++):
    if numbers_sorted_partially[current_sorted_amount - 1] > numbers_sorted_partially[current_sorted_amount]:
    break;

  4. for (int i = current_sorted_amount; i < numbers_amount; i++):
    if (numbers_sorted_partially[i] != numbers[i]):
    sorting_method = MergeSort

  5. if sorting_method == InsertionSort:
    print “Insertion Sort”
    sort(numbers, numbers + current_sorted_amount + 1)
    else:
    print “Merge Sort”
    current_sorted_amount *= 2
    for (int i = 0; i < numbers_amount / current_sorted_amount; i++):
    sort(numbers + i * current_sorted_amount, numbers + (i+1) * current_sorted_amount)

    sort(numbers + i * current_sorted_amount, numbers + numbers_amount)

  6. print numbers

完整提交代码

/*
# 问题分析
题设给定两组数, 第二组数是第一组数用插入排序或归并排序进行排序的某个中间状态,
要求判断使用的是哪种排序, 并用这种排序算法对排序的中间状态再排序一次并输出.

从题设中我们识别到两个功能需求:
    - 判断所使用的排序算法
    - 使用对应排序算法再进行一次排序

# 如果区分插入排序和归并排序
根据插入排序的特征, 排序过程中数组左半部分为排序部分, 右半部分为未排序部分.
而归并排序会同时变动整个数组.
题设保证了每组测试结果唯一, 所以不用担心出现插入排序和归并排序中间状态一致的情况.

我们只需要检查排序中间状态的数组是否符合"左边最长有序部分之外的另一部分是否是未排序部分(即与原数组对应部分完全西昂同)"
即, 检查第二个序列升序部分的末尾索引, 然后从该位置开始检查直到数组末尾是否都和原数组一致

# 得到插入排序的下一个结果
插入排序第n次的结果和第n+1次的结果, 差别在于: 左边有序部分的长度.
所以我们只需要对左起的n个元素进行排序, 其余部分不变, 排序的结果就是插入排序n次后的结果.

# 得到归并排序的下一个结果
归并排序第n次的结果和第n+1次的结果, 差别在于: 有序区块的长度.
比如对于数列 [3, 1, 2, 8, 7, 5, 9, 4, 6, 0]
第1次排序是以区块长度为1, 即 对[3], [1], [2], [8], [7], [5], [9], [4], [6], [0]的排序结果
第2次排序是以区块长度为2, 即 对[3, 1], [2, 8], [7, 5], [9, 4], [6, 0]的排序结果.
所以要得到第n次归并排序的结果, 我们只需要对每个长度为n的子数组进行排序, 末尾不足n的部分单独排序即可得到预期结果

# 完整描述步骤
1. 获取两组数列
2. 计算第二组数列从左起开始有序部分的末尾索引 k,
    检查从有序部分末尾索引开始直到整个数组结束, 是否每个值都跟原数组一致.
    如果一致, 说明右边部分没有被排序过, 则为 插入排序
    否则, 为归并排序
3. 如果是插入排序, 则将前k+1个元素进行排序(k为当前左边有序部分的长度)
    如果是归并排序, 则以k*2为区块长度, 从左往右对每个区块进行排序. 末尾不足k*2的部分也要单独排序

# 伪代码描述
1. get input of two array:
    - numbers_amount
    - numbers
    - numbers_sorted_partially
2. set current_sorted_amount = 1, sorting_method = InsertionSort;
3. for (; current_sorted_amount < numbers_amount; current_sorted_amount++):
    if numbers_sorted_partially[current_sorted_amount - 1] > numbers_sorted_partially[current_sorted_amount]:
        break;
4. for (int i = current_sorted_amount; i < numbers_amount; i++):
    if (numbers_sorted_partially[i] != numbers[i]):
        sorting_method = MergeSort
5. if sorting_method == InsertionSort:
    print "Insertion Sort"
    sort(numbers, numbers + current_sorted_amount + 1)
   else:
    print "Merge Sort"
    current_sorted_amount *= 2
    for (int i = 0; i < numbers_amount / current_sorted_amount; i++):
        sort(numbers + i * current_sorted_amount, numbers + (i+1) * current_sorted_amount)

    sort(numbers + i * current_sorted_amount, numbers + numbers_amount)

6. print numbers
*/

#include <stdio.h>
#define InsertionSortFlag 0
#define MergeSortFlag 1

int cmp(const void *a, const void *b)
{
    return (*(int *)a - *(int *)b);
}

void merge_sort_once(int number_amount, int *numbers, int *numbers_sorted_partially)
{
    for (int len = 1, i = 0; i < number_amount && len <= number_amount; len *= 2)
    {
        for (i = 0; i < number_amount && numbers[i] == numbers_sorted_partially[i]; i++)
            ;
        int j;
        for (j = 0; j < number_amount / len; j++)
        {
            qsort(numbers + j * len, len, sizeof(int), cmp);
        }
        qsort(numbers + j * len, number_amount % len, sizeof(int), cmp);
    }
}

int main()
{
    int number_amount;
    scanf("%d", &number_amount);

    int numbers[number_amount];
    int numbers_sorted_partially[number_amount];

    for (int i = 0; i < number_amount; i++)
    {
        scanf("%d", &numbers[i]);
    }

    for (int i = 0; i < number_amount; i++)
    {
        scanf("%d", &numbers_sorted_partially[i]);
    }

    int check_result = InsertionSortFlag;
    int sorted_amount = 1;
    for (; sorted_amount < number_amount; sorted_amount++)
    {
        if (numbers_sorted_partially[sorted_amount] < numbers_sorted_partially[sorted_amount - 1])
            break;
    }

    for (int i = sorted_amount; i < number_amount; i++)
    {
        if (numbers[i] != numbers_sorted_partially[i])
        {
            check_result = MergeSortFlag;
            break;
        }
    }

    if (check_result == MergeSortFlag)
    {
        printf("Merge Sort\n");
        merge_sort_once(number_amount, numbers, numbers_sorted_partially);
    }
    else
    {
        printf("Insertion Sort\n");
        qsort(numbers, sorted_amount + 1, sizeof(int), cmp);
    }

    for (int i = 0; i < number_amount; i++)
    {
        printf("%d", numbers[i]);
        if (i + 1 != number_amount)
        {
            printf(" ");
        }
    }
    printf("\n");
    return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 21:19:25  更:2022-09-24 21:21:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 18:36:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计