插入排序(直接插入排序和希尔排序)

一、直接插入排序

它的思想:每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。

下面我来说一下我的思路:

1.第一趟比较前两个数,然后把第二个数按大小插入到有序表中。

2.第二趟把第三个数据与前两个数从前向后扫描,把第三个数按大小插入到有序表中。

3.依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。

下面我用图来帮助大家理解:

实现代码:

void InsertSort(int *arr, size_t size)
{
	int end;//要排序的所有元素的最后一个元素的下标
	int tmp;
	for (int i = 0; i < size - 1; i++)
	{
		end = i;
		tmp = arr[end + 1];//最后一个元素保存起来
		//把所有大于最后一个元素的元素向后移动
		while (arr[end]>tmp&&end >= 0)
		{
			arr[end + 1] = arr[end];
			end--;
		}
		//把最后一个元素插入到不大于它的元素后面
		arr[end + 1] = tmp;
	}
}

二、希尔排序

希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。

希尔排序:将无序数组分割为若干个子序列,子序列不是逐段分割的,而是相隔特定的增量的子序列,对各个子序列进行插入排序;然后再选择一个更小的增量,再将数组分割为多个子序列进行排序......最后选择增量为1,即使用直接插入排序,使最终数组成为有序。

增量的选择:在每趟的排序过程都有一个增量,至少满足一个规则 增量关系 d[1] > d[2] > d[3] >..> d[t] = 1 (t趟排序);根据增量序列的选取其时间复杂度也会有变化,这个不少论文进行了研究,在此处就不再深究;本文采用首选增量为n/2,以此递推,每次增量为原先的1/2,直到增量为1;

下图详细讲解了一次希尔排序的过程:

代码实现:

void ShillSort(int *arr, size_t size)
{
	int end;//要排序的所有元素的最后一个元素的下标
	int gap = size / 2;//将数组分为size/2个子序列
	int tmp;//临时值
	for (gap = size / 2; gap > 0; gap /= 2)//增量递减
	{
		for (int i = gap; i < size ; i++)
		{
			if (arr[i]<arr[i - gap])
			{
				end = i - gap;
				tmp = arr[i];
				//当arr[end]>tmp时,移动
				while (arr[end]>tmp&&end >= 0)
				{
					arr[end + gap] = arr[end];
					end -= gap;
				}
				arr[end + gap] = tmp;
			}
		}
	}
}

希望大家能理解,写得不够好的地方,希望大家指出来。

时间: 2024-11-09 01:12:06

插入排序(直接插入排序和希尔排序)的相关文章

常见排序集合(冒泡排序,选择排序,直接插入排序,二分插入排序,快速排序,希尔排序,归并排序)

一下是一些常见的排序算法: 交换元素(后面算法都有用到): // 交换元素 private static void swap(int[] a, int i, int j) { int temp; temp = a[i]; a[i] = a[j]; a[j] = temp; } 冒泡排序(有优化): // 冒泡排序(优化①,②,③,④) private static void bubbleSort(int[] a) { boolean flag = false;// ①表示整个序列是无序的 for

排序之插入排序:直接插入和希尔排序

一.插入排序 1.思想:原理类似抓扑克牌,在有序表中进行插入和查找,插入合适的位置时,之后的元素需要往后移动 2.时间复杂度: 最好:O(N),正序情况,只有比较时间,无移动时间 最坏:O(N2),逆序情况 平均:O(N2) 3.辅助空间:O(1) 4.稳定性:稳定 5.适用场合:适用于初始序列基本有序的情况,或者n小的时候,插入排序效率高 1 public static void insertSort(int[] a) { 2 int target,i,j; 3 for(j = 1;j<a.l

基本排序算法(冒泡排序 选择排序 插入排序 快速排序 归并排序 基数排序 希尔排序)

冒泡排序 public static void bubbleSort(int[] arr){ int lgn = arr.length; for (int i = 0; i < lgn - 1; i++) { for (int j = 0; j < lgn - 1 - i; j++) { if(arr[j] > arr[j + 1]){ int temp = arr[j + 1]; arr[j + 1] = arr[j]; arr[j] = temp; } } } } 选择排序 publ

七大内部排序算法总结(插入排序、希尔排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序)

 写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列.因此排序掌握各种排序算法非常重要.对下面介绍的各个排序,我们假定所有排序的关键字都是整数.对传入函数的参数默认是已经检查好了的.只是简单的描述各个算法并给出了具体实现代码,并未做其他深究探讨. 基础知识: 由于待排序的记录数量不同,使得排序过程中设计的存储器不同,可将排序方法分为两大类:一类是内部排序,指的是待排序记录存放在计算机随机存储器中进行的排序过程.另一类是外部排序,

插入排序算法之希尔排序

一.前沿: 希尔排序(Shell Sort)的名称源于它的发明者Donald Shell,该算法是冲破了二次元时间屏障的算法之一.它通过比较相距一定间隔的元素工作,各趟所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟为止,因此希尔排序有时也叫做缩减增量排序(diminishing increament sort). 二.详细步骤: 希尔排序使用一个序列h1,h2,......ht 叫做   增量序列,只要h1=1,任何增量序列都是可行的,在使用hk的一趟增量序列后,数组中任何a[i]

浅谈希尔排序-----摘录

希尔排序 一.个人理解 希尔排序(Shell Sort)是插入排序的一种.是针对直接插入排序算法的改进.该方法又称缩小增量排序,因DL.Shell于1959年提出而得名. 其实,希尔排序本质也就是直接插入算法的升级,希尔的基本思想,就是先将整个待排元素序列分割成若干个子序列(由相隔某个"增量"的元素组成的)分别进行直接插入排序,然后依次缩减增量大小再进行排序,待整个序列中的元素基本有序(增量足够小,通常为1)时,再对全体元素进行一次直接插入排序. (直接插入的原理:把一个标记插入到已经

希尔排序法(Shell Sort)

希尔排序法(缩小增量法) 属于插入类排序,是将整个无序列分割成若干小的子序列分别进行插入排序的方法.希尔排序是非稳定排序算法.该方法因DL.Shell于1959年提出而得名. 希尔排序是基于插入排序的以下两点性质而提出改进方法的: 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率. 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位. 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序:随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1

希尔排序java

希尔排序简述 希尔排序是基于插入排序的以下两点性质而提出改进方法的: 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率.(希尔排序先将部分数据进行排序,相当于已经部分排好序) 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位.(希尔排序先将间隔大的数据进行大的移位,后期的移位距离相对要小很多) 分析: 先去一个小于n的整数的H作为第一个增量,把文件的全部记录分组.即将所有距离为H的倍数的记录放在同一个族中,先在各组内进行直接插入排序:然后去第二个增量重复上述

排序——希尔排序

希尔排序(Shell Sort)是插入排序的一种.是针对直接插入排序算法的改进.该方法又称缩小增量排序,因DL.Shell于1959年提出而得名. 基本思想: 先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组.所有距离为d1的倍数的记录放在同一个组中.先在各组内进行直接插入排序:然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<-<d2<d1),即所有记录放在同一组中进行直接插入排序为止. 希尔排序的实现代码: #inclu

【算法拾遗(java描述)】--- 插入排序(直接插入排序、希尔排序)

插入排序基本思想 每次将一个待排序的记录按其关键字大小插入到前面已经拍好序的子文件的适当位置,直到全部记录插入完成为止. 直接插入排序 基本思想 直接插入排序的基本操作是将一个记录插入到已排好序的有序表中,从而得到一个新的有序表.即假设待排序的记录存放在数组R[1······n]中,排序过程中,R被分成两个子区间R[1······i]和R[i+1······n],其中,R[1······i]是已经排好序的有序区:R[i+1······n]是当前未排序的部分.将当前无序区的第一个记录R[i+1]插