原题链接:https://vjudge.net/problem/Aizu-ALDS1_1_A

题目描述

Write a program of the Insertion Sort algorithm which sorts a sequence A in ascending order. The algorithm should be based on the following pseudocode:

for i = 1 to A.length-1
key = A[i]
/* insert A[i] into the sorted sequence A[0,...,j-1] */
j = i - 1
while j >= 0 and A[j] > key
A[j+1] = A[j]
j--
A[j+1] = key

Note that, indices for array elements are based on 0-origin.

To illustrate the algorithms, your program should trace intermediate result for each step.

Input

The first line of the input includes an integer N, the number of elements in the sequence.

In the second line, N elements of the sequence are given separated by a single space.

Output

The output consists of N lines. Please output the intermediate sequence in a line for each step. Elements of the sequence should be separated by single space.

Constraints

1 ≤ N ≤ 100

Sample Input 1

6
5 2 4 6 1 3

Sample Output 1

5 2 4 6 1 3
2 5 4 6 1 3
2 4 5 6 1 3
2 4 5 6 1 3
1 2 4 5 6 3
1 2 3 4 5 6

Sample Input 2

3
1 2 3

Sample Output 2

1 2 3
1 2 3
1 2 3

讲解

插入排序法

  • 将开头元素视作已排序
  • 执行下述处理,直至未排序部分消失
  1. 取出未排序部分的开头元素赋给变量v。
  2. 在已排序部分,将所有比v大的元素向后移动一个单位。
  3. 将已取出的元素v插入空位。

举例说明

当对数组A = {8,3,1,5,2,1}进行从小到大的插入排序时,流程如下

0.

1.

将开头元素A[0](=8)视为已排序,所以我们取出A[1]中的3,将其插入已排序部分的恰当位置。

首先把原先位于A[0]的8移动至A[1],再把3插入A[0]。

2.

首先将比1大的A[1](=8)和A[0](=3)顺次向后移动一个位置,然后把1插入A[0]。

3.

首先将比5大的A[2](=8)向后移动一个位置,然后把5插入A[2]。

4.

首先将比5大的A[3](=8)向后移动一个位置,然后把2插入A[1]。

5.

首先将比5大的A[4](=8)向后移动一个位置,然后把1插入A[1]。

6.

排序完成。

插入排序法所需的主要变量

A[N]

长度为N的整型数组

i

循环变量,表示未排序部分的开头元素

v

临时保存A[i]值的变量

j

循环变量,用于在已排序部分寻找v的插入位置

外层循环的 i 从1开始自增。在每次循环开始时,将A[i]的值临时保存在变量v中。

接下来是内部循环:从已排序部分找出比v大的元素并让它们顺次后移一个位置。在这里,我们让 j 从 i - 1 开始向前自减,同时将比v大的元素从A[j]移动到A[j+1]。一旦j等于-1或当前A[j]小于等于v则结束循环,并将v插入当前 j+1 的位置。

程序代码及细节

#include<stdio.h>
void trace(int A[],int N){ //按顺序输出数组元素
int i;
for(i=;i<N;i++){
if(i>) printf(" "); //在相邻元素之间输出1个空格
printf("%d",A[i]);
}
printf("\n");
} void insertionSort(int A[],int N){ //插入排序(数组下标从0开始)
int j,i,v;
for(i=;i<N;i++){
v=A[i];
j=i-;
while(j>= && A[j]>v){
A[j+]=A[j];
j--;
}
A[j+]=v;
trace(A,N);
}
} int main()
{
int N,i,j;
int A[];
scanf("%d",&N);
for(i=;i<N;i++)
scanf("%d",&A[i]);
trace(A,N);
insertionSort(A,N);
return ;
}

细节关注

  • 数组长度是否足够长
  • 是否搞错了0起点和1起点的数组下标
  • 是否误用了循环变量
  • 是否输出了多余的空格或换行

总结

稳定性:在插入排序法中,我们只将比v(取出的值)大的元素向后平移,不相邻的元素不会直接交换位置,因此十分稳定

时间复杂度:最坏的情况下,每个 i 循环都需要执行 i 次移动,总共需要1 + 2 + ... + N - 1 = (N2 - N)/ 2 次移动,即算法复杂度为 O(N2

算法优势:可以快速处理相对有序的数据

Aizu_Insertion Sort的更多相关文章

  1. [算法]——归并排序(Merge Sort)

    归并排序(Merge Sort)与快速排序思想类似:将待排序数据分成两部分,继续将两个子部分进行递归的归并排序:然后将已经有序的两个子部分进行合并,最终完成排序.其时间复杂度与快速排序均为O(nlog ...

  2. [算法]——快速排序(Quick Sort)

    顾名思义,快速排序(quick sort)速度十分快,时间复杂度为O(nlogn).虽然从此角度讲,也有很多排序算法如归并排序.堆排序甚至希尔排序等,都能达到如此快速,但是快速排序使用更加广泛,以至于 ...

  3. shell之sort命令

    1 sort的工作原理 sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出. [rocrocket@rocrocket progr ...

  4. 详细解说 STL 排序(Sort)

    0 前言: STL,为什么你必须掌握 对于程序员来说,数据结构是必修的一门课.从查找到排序,从链表到二叉树,几乎所有的算法和原理都需要理解,理解不了也要死记硬背下来.幸运的是这些理论都已经比较成熟,算 ...

  5. SQL Tuning 基础概述06 - 表的关联方式:Nested Loops Join,Merge Sort Join & Hash Join

    nested loops join(嵌套循环)   驱动表返回几条结果集,被驱动表访问多少次,有驱动顺序,无须排序,无任何限制. 驱动表限制条件有索引,被驱动表连接条件有索引. hints:use_n ...

  6. js sort() reverse()

    数组中存在的两个方法:sort()和reverse() 直接用sort(),如下: ,,,,,,,,,,,]; console.log(array.sort());ps:[0, 1, 2, 2, 29 ...

  7. Java中的经典算法之冒泡排序(Bubble Sort)

    Java中的经典算法之冒泡排序(Bubble Sort) 神话丿小王子的博客主页 原理:比较两个相邻的元素,将值大的元素交换至右端. 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面.即在第一 ...

  8. 2.sort 排序命令讲解

    sort命令  sort:文本排序,仅仅是对显示文件的排序,而不影响源文件的顺序,是根据ASSII码     的字符升序来排列的.        -n:安装数值大小从小到大排列 ,默认是升序.     ...

  9. 基本shell编程【3】- 常用的工具awk\sed\sort\uniq\od

    awk awk是个很好用的东西,大量使用在linux系统分析的结果展示处理上.并且可以使用管道, input | awk ''  | output 1.首先要知道形式 awk 'command' fi ...

随机推荐

  1. markModified声明要修改的数组字段

    更新一个文档的字段的时候,如果该字段的类型是数组类型,则必须在更新保存前声明一下这个数组字段要被修改,否则这个数组字段的值不会被修改.如 article.markModified('categorys ...

  2. FFmpeg(11)-基于FFmpeg进行音频重采样(swr_init(), swr_convert())

    一.包含头文件和库文件 修改CMakeLists # swresample add_library(swresample SHARED IMPORTED) set_target_properties( ...

  3. vue中的filters的用法

    1.效果 金额保留两位小数,并加上单位元 2.index.html <!DOCTYPE html> <html lang="en"> <head> ...

  4. 【设计模式】适配器模式与Reader、InputStream之间的适配

    简述 适配器模式,目的是将A对象通过适配.转换的方式转换成B对象来使用,为什么转换为B对象?因为用户通过依赖B对象来使用. 适配器的实现有两种方式. 继承实现 组合实现 基于Java单继承的机制,组合 ...

  5. 玩转Bootstrap(JS插件篇)-第1章 模态弹出框 :1-4 模态弹出框--结构分析

    模态弹出框--结构分析 Bootstrap框架中的模态弹出框,分别运用了“modal”.“modal-dialog”和“modal-content”样式,而弹出窗真正的内容都放置在“modal-con ...

  6. Python学习笔记(4):容器、迭代对象、迭代器、生成器、生成器表达式

    在了解Python的数据结构时,容器(container).可迭代对象(iterable).迭代器(iterator).生成器(generator).列表/集合/字典推导式(list,set,dict ...

  7. 设计模式之工厂方法模式(代码用Objective-C展示)

    前面一篇展示了一个简单工厂模式,这一篇主要是对比,工厂方法模式比简单工厂模式好在哪里?为什么要用这个模式?这个模式的精髓在哪里? 就以计算器为例,结果图如下: 加减乘除运算都是继承自基类运算类,然后工 ...

  8. Android开发(三)——Android布局中实现圆角边框

    设置corners_bg.xml(设置边框圆角可以在drawable-mdpi目录里定义一个xml): <?xml version="1.0" encoding=" ...

  9. JAVA-JSP内置对象之exception对象用来处理错误异常

    相关资料:<21天学通Java Web开发> exception对象1.exception对象用来处理错误异常.2.如果要使用exception对象,必须指定page中的isErrorPa ...

  10. C#学习笔记(25)——用刻盘器批量从U盘删除添加文件

    说明(2017-11-17 14:46:05): 1. 因为经常要从U盘里面删除版本,然后添加版本,每次都要几个人手动复制粘贴,费时费力,就花了一下午时间写了个程序,自动删除和添加版本. 2. Dri ...