【C++数据结构——内排序】希尔排序(头歌实践教学平台习题)【合集】

目录😋

任务描述

相关知识

1. 排序算法基础概念

2.插入排序知识

3. 间隔序列(增量序列)的概念

4. 算法的时间复杂度和空间复杂度分析

5. 代码实现技巧(如循环嵌套、索引计算)

测试说明

我的通关代码:

测试结果:


任务描述

本关任务:实现希尔排序算法。

相关知识

为了完成本关任务,你需要掌握:

  1. 排序算法基础概念
  2. 插入排序知识
  3. 间隔序列(增量序列)的概念
  4. 算法的时间复杂度和空间复杂度分析
  5. 代码实现技巧(如循环嵌套、索引计算)

1. 排序算法基础概念

        排序算法是将一组数据按照特定的顺序(通常是升序或降序)进行重新排列的算法。常见的排序算法有冒泡排序、插入排序、选择排序、快速排序、归并排序等等。排序算法的稳定性也是一个重要概念,稳定排序是指在排序过程中,相等元素的相对顺序保持不变;不稳定排序则可能改变相等元素的相对顺序。其主要目的就是为了更方便地对数据进行查找、比较等操作,提高数据处理的效率。

2.插入排序知识

  1. 基本思想
    • 希尔排序是基于插入排序改进而来的。插入排序的基本思想是把待排序的元素插入到已经排好序的部分序列中合适的位置,直到整个序列都变为有序。就好比整理一手扑克牌,每次拿到一张新牌,将它插入到已经整理好顺序的那部分牌里合适的位置。
    • 具体步骤示例(以升序为例):
      • 首先,将数组的第一个元素看作是已经排好序的序列,长度为 1。
      • 然后从第二个元素开始,依次将后面的元素插入到前面已排好序的序列中。比如对于元素 arr[i]i 从 1 开始),将它与前面已排好序的元素 arr[j]j 从 i - 1 开始,逐步往前递减)进行比较,如果 arr[i] 小于 arr[j],就把 arr[j] 往后移一位,直到找到合适的位置(即 arr[i] 大于等于某个 arr[j]),将 arr[i] 插入进去。
    • 代码示例:
      #include <iostream>
      #include <vector>
      using namespace std;
      
      // 插入排序函数
      vector<int> insertion_sort(vector<int> arr) {
          for (size_t i = 1; i < arr.size(); ++i) {
              int key = arr[i];
              int j = i - 1;
              while (j >= 0 && arr[j] > key) {
                  arr[j + 1] = arr[j];
                  j--;
              }
              arr[j + 1] = key;
          }
          return arr;
      }

3. 间隔序列(增量序列)的概念

        在一些改进的排序算法(比如希尔排序)中会用到间隔序列(增量序列)。它是指在排序过程中,确定元素比较和移动的间隔大小的序列。比如希尔排序刚开始时,间隔可能比较大,这样可以让元素快速地大致移动到它最终位置的附近,然后随着排序的进行,间隔逐渐缩小,最后间隔为 1 时,就相当于进行普通的插入排序了。常用的增量序列有希尔本人提出的  N/2, N/4, N/8,..., 1N 为待排序元素个数)等不同形式,不同的增量序列对算法的效率等方面会有影响。

4. 算法的时间复杂度和空间复杂度分析

  • 时间复杂度
    用来衡量算法运行所需要的时间长短,通常用大 O 表示法来描述。它关注的是随着输入规模(比如数组元素个数 n)的增大,算法执行基本操作(如比较、交换、赋值等)的次数的增长趋势。例如插入排序在最坏情况下(数组是逆序的),时间复杂度是 O(n²),因为对于每个元素,都可能需要和前面已经排好序的所有元素依次比较和移动;在最好情况下(数组已经有序),时间复杂度是 O(n),只需要进行 n - 1 次比较操作即可。
  • 空间复杂度
    衡量算法在运行过程中临时占用的存储空间大小,同样用大 O 表示法。像插入排序,它只需要常数个额外的空间(比如用来暂存当前要插入的元素等),所以空间复杂度是 O(1),属于原地排序算法,也就是不需要额外开辟大量和输入规模相关的存储空间就能完成排序。

5. 代码实现技巧(如循环嵌套、索引计算)

  • 循环嵌套
    在很多排序算法中都会用到循环嵌套。例如插入排序中,外层循环控制遍历整个数组(从第二个元素开始),内层循环用来在已排好序的部分序列里找到合适的插入位置,进行元素的比较和移动。合理运用循环嵌套可以按照设定的逻辑依次处理每个元素以及它们之间的关系,不过要注意循环的边界条件等设置,避免出现越界等错误。
  • 索引计算
    准确的索引计算对于排序算法的正确实现至关重要。比如在插入排序里,要通过索引准确地找到当前元素、前面已排好序的元素,以及在移动元素时更新正确的索引位置。像 arr[j + 1] = arr[j] 这样的语句中,通过正确的索引 j 和 j + 1 来实现元素的后移操作,而且在不同的循环条件下要确保索引始终处于合理的范围,保证算法逻辑的正确性。

测试说明

平台会对你编写的代码进行测试:

测试输入示例:
10
9 8 7 6 5 4 3 2 1 0 
(说明:第一行是元素个数,第二行是待排序的原始关键字数据。)

输出示例:
排序前:9 8 7 6 5 4 3 2 1 0 
  d=5: 4 3 2 1 0 9 8 7 6 5 
  d=2: 0 1 2 3 4 5 6 7 8 9 
  d=1: 0 1 2 3 4 5 6 7 8 9 
排序后:0 1 2 3 4 5 6 7 8 9 

开始你的任务吧,祝你成功!


我的通关代码:

#include <malloc.h>
#include <stdio.h>

#define MAXL 100     //最大长度
typedef int KeyType; //定义关键字类型为int
typedef char InfoType;

typedef struct {
  KeyType key;   //关键字项
  InfoType data; //其他数据项,类型为InfoType
} RecType;       //查找元素的类型

// 创建顺序表
void CreateList(RecType R[], KeyType keys[], int n) {
  for (int i = 0; i < n; i++) // R[0..n-1]存放排序记录
    R[i].key = keys[i];
}

// 输出顺序表
void DispList(RecType R[], int n) {
  for (int i = 0; i < n; i++)
    printf("%d ", R[i].key);
  printf("\n");
}

// 显示一趟划分后的结果(这里在希尔排序中主要用于展示每趟按不同间隔排序后的结果)
void disppart(RecType R[], int s, int t) {
  for (int i = 0; i < s; i++)
    printf("    ");
  for (int i = s; i <= t; i++)
    printf("%3d ", R[i].key);
  printf("\n");
}

// 希尔排序算法主体
void ShellSort(RecType R[], int n) {
  int d, i, j;
  RecType tmp;
  // 初始化间隔序列,这里采用常用的Hibbard间隔序列(2^k -
  // 1),从n/2开始逐步缩小间隔
  for (d = n / 2; d > 0; d /= 2) {
    printf("  d=%d: ", d);
    // 对每个间隔下的子序列进行插入排序
    for (i = d; i < n; i++) {
      tmp = R[i];
      j = i - d;
      while (j >= 0 && R[j].key > tmp.key) {
        R[j + d] = R[j];
        j -= d;
      }
      R[j + d] = tmp;
    }
    // 输出当前间隔下排序后的结果
    DispList(R, n);
  }
}

int main() {
  int n;
  scanf("%d", &n);
  KeyType keys[MAXL];
  RecType R[MAXL];
  for (int i = 0; i < n; i++)
    scanf("%d", &keys[i]);
  CreateList(R, keys, n);
  printf("排序前:");
  DispList(R, n);

  ShellSort(R, n);

  printf("排序后:");
  DispList(R, n);

  return 0;
}

测试结果:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/949690.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

每天看一个Fortran文件(9)

最后的输出变量是f 这里面调用了一个关键的子程序&#xff0c;spectral_nudging_filter_fft_2d_ncar 这是一个谱逼近的二维快速傅里叶变换过滤的程序。 二维的滤波这个还不是很清楚&#xff0c;找找技术文件看下 超详细易懂FFT&#xff08;快速傅里叶变换&#xff09;及代码…

Centos源码安装MariaDB 基于GTID主从部署(一遍过)

MariaDB安装 安装依赖 yum install cmake ncurses ncurses-devel bison 下载源码 // 下载源码 wget https://downloads.mariadb.org/interstitial/mariadb-10.6.20/source/mariadb-10.6.20.tar.gz // 解压源码 tar xzvf mariadb-10.5.9.tar.gz 编译安装 cmake -DCMAKE_INSTA…

【通俗理解】AI的两次寒冬:从感知机困局到深度学习前夜

AI的两次寒冬&#xff1a;从感知机困局到深度学习前夜 引用&#xff08;中英双语&#xff09; 中文&#xff1a; “第一次AI寒冬&#xff0c;是因为感知机局限性被揭示&#xff0c;让人们失去了对算法可行性的信心。” “第二次AI寒冬&#xff0c;则是因为专家系统的局限性和硬…

数据结构9.3 - 文件基础(C++)

目录 1 打开文件字符读写关闭文件 上图源自&#xff1a;https://blog.csdn.net/LG1259156776/article/details/47035583 1 打开文件 法 1法 2ofstream file(path);ofstream file;file.open(path); #include<bits/stdc.h> using namespace std;int main() {char path[]…

下载ffmpeg执行文件

打开网址&#xff1a;Download FFmpeg 按下面步骤操作 解压文件就可以看到ffmpeg的执行文件了&#xff0c;需要通过命令行进行使用&#xff1a; ffmpeg命令行使用参考&#xff1a; ffmpeg 常用命令-CSDN博客

网络安全抓包

#知识点&#xff1a; 1、抓包技术应用意义 //有些应用或者目标是看不到的&#xff0c;这时候就要进行抓包 2、抓包技术应用对象 //app,小程序 3、抓包技术应用协议 //http&#xff0c;socket 4、抓包技术应用支持 5、封包技术应用意义 总结点&#xff1a;学会不同对象采用…

国产编辑器EverEdit - 两种删除空白行的方法

1 使用技巧&#xff1a;删除空白行 1.1 应用场景 用户在编辑文档时&#xff0c;可能会遇到很多空白行需要删除的情况&#xff0c;比如从网页上拷贝文字&#xff0c;可能就会存在大量的空白行要删除。 1.2 使用方法 1.2.1 方法1&#xff1a; 使用编辑主菜单 选择主菜单编辑 …

可以输入的下拉框(下拉框数据过大,页面卡死)

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 在项目中&#xff0c;有些下拉框的数据过于庞大&#xff0c;这样页面有时候会卡死&#xff0c;在vue3中常用的组件库element-puls中有个组件可以避免 在项目中&#xff0c;有些需求要求下拉框选择的同…

基于Python的音乐播放器 毕业设计-附源码73733

摘 要 本项目基于Python开发了一款简单而功能强大的音乐播放器。通过该音乐播放器&#xff0c;用户可以轻松管理自己的音乐库&#xff0c;播放喜爱的音乐&#xff0c;并享受音乐带来的愉悦体验。 首先&#xff0c;我们使用Python语言结合相关库开发了这款音乐播放器。利用Tkin…

谷粒商城-高级篇完结-Sleuth+Zipkin 服务链路追踪

1、基本概念和整合 1.1、为什么用 微服务架构是一个分布式架构&#xff0c;它按业务划分服务单元&#xff0c;一个分布式系统往往有很多个服务单元。由于服务单元数量众多&#xff0c;业务的复杂性&#xff0c;如果出现了错误和异常&#xff0c;很难去定位 。主要体现在&#…

ollama+FastAPI部署后端大模型调用接口

ollamaFastAPI部署后端大模型调用接口 记录一下开源大模型的后端调用接口过程 一、ollama下载及运行 1. ollama安装 ollama是一个本地部署开源大模型的软件&#xff0c;可以运行llama、gemma、qwen等国内外开源大模型&#xff0c;也可以部署自己训练的大模型 ollama国内地…

pandas系列----DataFrame简介

DataFrame是Pandas库中最常用的数据结构之一&#xff0c;它是一个类似于二维数组或表格的数据结构。DataFrame由多个列组成&#xff0c;每个列可以是不同的数据类型&#xff08;如整数、浮点数、字符串等&#xff09;。每列都有一个列标签&#xff08;column label&#xff09;…

Unity【Colliders碰撞器】和【Rigibody刚体】的应用——小球反弹效果

目录 Collider 2D 定义&#xff1a; 类型&#xff1a; Rigidbody 2D 定义&#xff1a; 属性和行为&#xff1a; 运动控制&#xff1a; 碰撞检测&#xff1a; 结合使用 实用检测 延伸拓展 1、在Unity中优化Collider 2D和Rigidbody 2D的性能 2、Unity中Collider 2D…

Java实现UDP与TCP应用程序

三、Java实现UDP应用程序 3.1 InetAddress类 java.net.InteAddress类是用于描述IP地址和域名的一个Java类&#xff1b; 常用方法如下&#xff1a; public static InetAddress getByName(String host)&#xff1a;根据主机名获取InetAddress对象public String getHostName()…

信号处理-消除趋势项

matlab 版本 python 版本 import numpy as np import matplotlib.pyplot as plt from matplotlib import rcParams# 设置中文字体 rcParams[font.sans-serif] [SimHei] # 设置默认字体为黑体 rcParams[axes.unicode_minus] False # 解决负号显示问题def compute_time(n, f…

Linux 安装 meilisearch

前言 由于项目部分数据需要用到搜索引擎进行检索&#xff0c;但是服务器资源有限&#xff0c;安装elasticsearch过于笨重&#xff0c;不太符合现实情况&#xff0c;所以选择了meilisearch作为搜索引擎来使用&#xff0c;目前使用接近一年&#xff0c;运行良好。 安装 在/usr/…

【C++数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 1. 二叉排序树的基本概念 2. 二叉排序树节点结构体定义 3. 创建二叉排序树 4. 判断是否为二叉排序树 5. 递归查找关键字为 6 的结点并输出查找路径 6. 删除二叉排序树中的节点 测试说明 通关代码 测试结果 任务描述 本关任务&a…

TCP与DNS的报文分析

场景拓扑&#xff1a; 核心路由配置&#xff1a; 上&#xff08;DNS&#xff09;&#xff1a;10.1.1.1/24 下(WEB)&#xff1a;20.1.1.1/24 左&#xff08;client&#xff09;&#xff1a;192.168.0.1/24 右(PC3)&#xff1a;192.168.1.1/24Clint2配置&a…

OpenHarmony通过挂载镜像来修改镜像内容,RK3566鸿蒙开发板演示

在测试XTS时会遇到修改产品属性、SElinux权限、等一些内容&#xff0c;修改源码再编译很费时。今天为大家介绍一个便捷的方法&#xff0c;让OpenHarmony通过挂载镜像来修改镜像内容&#xff01;触觉智能Purple Pi OH鸿蒙开发板演示。搭载了瑞芯微RK3566四核处理器&#xff0c;树…

linux ansible部署

ansible部署完后&#xff0c;执行报错 # ansible one -i hosts -m ping dataos193 | FAILED! > {"msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add …