首页 > 编程语言 >【八大数据排序法】希尔排序法的图形理解和案例实现 | C++

【八大数据排序法】希尔排序法的图形理解和案例实现 | C++

时间:2023-02-03 13:31:49浏览次数:47  
标签:插入排序 算法 C++ 希尔 排序 数据 复杂度

image.png

第十七章 希尔排序法


::: hljs-center

目录

第十七章 希尔排序法

●前言

●认识排序

●一、希尔排序法是什么?

1.简要介绍

2.图形理解

3.算法分析

●二、案例实现

1.案例一

●总结

:::

前言

排序算法是我们在程序设计中经常见到和使用的一种算法,它主要是将一堆不规则的数据按照递增或递减的方式重新进行排序。在如今的互联网信息时代,随着大数据和人工智能的发展,大型企业的数据库中有亿级的用户数据量。因此对其进行处理,排序算法也就成为了其中必不可缺的步骤之一。


认识排序

排序功能对计算机领域而言,是一项非常重要而且普遍的工作。排序中数据的移动方式可分为直接移动和逻辑移动两种方式,直接移动是直接交换存储数据的位置,而逻辑移动并不会移动数据存储的位置,仅改变指向这些数据辅助指针的值。排序通常按照数据量的多少和所使用的内存,可分为内部排序和外部排序,数据量小可以全部加载到内存来进行排序的,就称为内部排序,大部分排序属于此类。数据量大而无法一次性加载到内存中,必须借助磁带,磁盘等辅助存储器进行排序的,则称为外部排序。随着数据结构科学的进步,如今,陆续被提出的冒泡排序法,选择排序法,插入排序法,合并排序法,快速排序法,堆积排序法,希尔排序法,基数排序法,直接合并排序法等等,它们各有其特色和其应用场合。并且在算法中,我们非常关注算法程序代码的时间复杂度和空间复杂度,因为它会直接体现出我们程序代码的执行效率以及编程人员的逻辑思维等等的综合能力。当数据量相当庞大时,排序算法所花费的时间就显得相当重要,排序算法的时间复杂度可分为最好情况、最坏情况以及平均情况。另外,对于任何的排序算法都会有数据交换的操作,数据互换位置会暂时用到一个额外的空间,这也是排序算法中空间复杂度要考虑到的问题,而在排序算法中所使用的额外空间越小,它的空间复杂度就越好。


一、希尔排序法是什么?

1.简要介绍

希尔排序法是D.L.Shell在1959年发明的一种排序方法,它可以减少插入排序法中数据搬移的次数,从而去加速排序的进行。它的原则是将数据区分成特定间隔的几个小区快,以插入排序法排完区块内的数据后再渐渐减少间隔的距离。

2.图形理解

用希尔排序法对下面的8个数据元素进行从小到大的排序,具体情况如下图所示: image.png 首先将所有数据分成Y份(8/2),即分成4份将其称为划分数。注意,划分数不一定是2,但是质数是最好的,所以为了方便计算,我们最终会将其化为2份。因此一开始的间隔划分为4,具体情况如下图所示 image.png 如此就可以得到4个区块,分别是(63,45)(92,71)(27,58)(36,7),再分别用插入排序法排序为(45,63)(71,92)(27,58)(7,36)。具体情况如下图所示: image.png 接着去缩小间隔为((8/2)/2),具体情况如下图所示: image.png 再分别用插入排序法对(45,27,63,58)(71,7,92,36)进行排序,排序结果为(27,45,58,63)(7,36,71,92)。具体情况如下图所示: image.png 再以(((8/2)/2)/2)的间隔去进行分区的插入排序,即对每一个元素进行排序。具体情况如下图所示: image.png 最终的情况下即用插入排序法对(27,7,45,36,58,71,63,92)这个八个数据元素进行排序,排序结果为(7,27,36,45,58,63,71,92)。具体情况如下图所示: image.png

3.算法分析

①希尔排序法和插入排序法一样,都属于稳定排序法。 ②希尔排序法只需要一个额外的空间,因此空间复杂度为最佳。 ③希尔排序法适用于大部分数据都已经排好了的情况。 ④该排序法在任何情况下的时间复杂度都为O(n^3/2)。

二、案例实现

1.案例一

①范例程序:用希尔排序法对7、66、2、40、30、67、90、11这八个数据元素进行排序,并且输出每次希尔分区后排序下的结果状态。 ②代码展示:

#include<iostream>
using namespace std;
#define size 8 //事先声明排序数据的个数
class shell {
public:
	int data[size];
	void showresult(){
		for (int i = 0; i < size; i++)
			cout <<" " << data[i];
		cout << endl;
	}
	void shell_start() { 
		int k = 0;    //打印计数
		int jump = size / 2;   //分区的间距位移量
		while (jump != 0)
		{
			for (int i = jump; i < size; i++)    //每次分区后的扫描次数
			{
				int temp = data[i];    //展示存储数据
				int j = i - jump;    //定位比较元素
				while (temp<data[j]&&j>=0)     //插入排序法的基本算法,只不过下标参数有所改变
				{
					data[j + jump] = data[j];
					j-=jump;
				}
				data[jump+j] = temp;
			}
			cout << "第" << ++k << "次扫描:";
			showresult();
			jump /= 2;   //控制整体循环数,即分区的次数
		}
	}
};
void text()
{
	shell s;
	cout << "请输入要排序的" << size << "个数据" << endl;
	for (int i = 0; i < size; i++)
		cin >> s.data[i];
	cout << "排序前:" << endl;
	s.showresult();
	s.shell_start();
	cout << "排序后:" << endl;
	s.showresult();
}
int main()
{
	text();
}

③结果展示: image.png


总结

以上就是希尔排序法的讲解,从上面的图形以及代码中不难看出,希尔排序法是经过插入排序法进行修改而创新出的一种新的排序方法。该排序法的鲜明特征就体现在了它的分区块思想上,将一个大序列多次分成多个小的子序列进行比较排序,我认为这是一种很好的思想。我们学算法,重要的不是去学习记忆那些固定的算法的代码段,而是去体会不同算法的编程思想,从而将其合理的运用到我们的程序代码中。

<您的三连和关注是我最大的动力>

标签:插入排序,算法,C++,希尔,排序,数据,复杂度
From: https://blog.51cto.com/zhangzhichaoya/6035802

相关文章

  • c++中调用QML中的函数和设置QML中的属性的问题
    1.这里主要是介绍,如何在c++中调用QML中的函数和设置QML中的属性的问题  2.具体代码    //UICtest.qmlimportQt4.7Rectangle{   id:mainWid......
  • POJ 2299 Ultra-QuickSort(树状数组+离散化 或 归并排序求逆序)
    DescriptionInthisproblem,youhavetoanalyzeaparticularsortingalgorithm.Thealgorithmprocessesasequenceofndistinctintegersbyswappingtwoadjace......
  • C/C++编译链接
    一、编译链接过程名词解释编译:由编译器对各个源文件进行词法分析、语法分析、语义分析等操作,最终生成多个目标文件。由于这些文件可能存在互相调用对方的函数或变量,还......
  • 现代C++实战30讲
    本文记录学习吴咏炜老师的《现代C++实战》课程的心得体会,记录自认为值得记录的知识点。重新认识的点如果临时对象被绑定到一个引用上,则它的生命周期会延长到跟这个引用......
  • 现代C++实战30讲(2)
    本文记录学习吴咏炜老师的《现代C++实战》课程的心得体会,记录自认为值得记录的知识点。重新认识的点编译期间的多态所有容器类都有begin和end函数成员,这为通用遍......
  • c++学习2 基础关键词
    三volatile强制访问内存在一个变量的频繁使用中,系统为了提高效率,会自动将内存里面的数据放入CPU里的寄存器里。但在某些特殊场景下,放入寄存器这个操作反倒会导致CPU无法......
  • C++ 虚函数底层表达
    转载一篇乐哥的博客,对虚函数,虚函数表和派生类对象赋予给基类指针时地址的变化等会有更深的理解https://mp.weixin.qq.com/s?__biz=Mzk0MzI4OTI1Ng==&mid=2247489554&idx=1......
  • C语言学习: 快速排序(递归方式)
    1#include<stdio.h>2#include"io_utils.h"3#include<stdlib.h>4#include<time.h>56#definePLAYER_COUNT5078voidSwapElements(intarray[......
  • 选择排序
    #include<iostream>#include<vector>usingnamespacestd;/***插入排序*首先找到数组中最小的元素和第一个元素进行交换*再次找到剩下的数组元素中最小的元......
  • C++迭代器种类与编译期间多态
    迭代器分类C++STL中根据移动能力将迭代器分成了5类:InputIterator输入迭代器,只支持operator++操作。OutputIterator输出迭代器,只支持operator++操作。......