原题链接: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. Android 编程下的日志工具类

    package com.sunzn.app.util; import android.util.Log; public class Logger { public static int DEBUG_L ...

  2. Windows下MFC程序利用LockCop解决死锁

    死锁现象:在训练的时候,点击“终止”按钮时不时会发生死锁. 检测工具:LockCop.TRACE宏.::GetCurrentThreadID函数. 检测手段: 总结起来就是—— 第一步:用LockCo ...

  3. android之滑屏的实现

    ★理论知识 ●View在屏幕上显示出来要先经过measure(计算)和layout(布局).  ◆当控件的父元素正要放置该控件时调用,父元素会问子控件“你想要用多大的地方?”,然后传入两个参数widt ...

  4. ASP.NET学习笔记(5)——原生Ajax基本操作

    说明(2017-11-4 15:32:49): 1. 回北京后又快一个月了,上次在家写的下回预告,到底是没把加水印写完,而且这次也不想写.. 2. 上次许的愿,十月份看完asp.net,已经泡汤了,翻 ...

  5. git的使用总结

    git使用技巧 git使用技巧 windows下git使用 git ignore file git 打tag vim编码设置 git ls显示中文乱码问题 git view history 查看某个文 ...

  6. mysql 常用语句记录

    一.表的状态查询   (1)如果发现一个数据异常的大了,需要查看一下其中哪些表变大了,可以使用如下命令 SQL> SHOW TABLE STATUS FROM 数据库名 LIKE 数据表名;   ...

  7. REST接口调用经验

    1. 调用接口的时候对于参数或返回值的单位一定要注意啊,比如有的分数用的百分制,有的用的小数...,坑大了

  8. Go Revel - Controllers(控制器)

    Controller(控制器)整个revel都是围绕它处理所有请求 控制器可以是任何直接或间接内嵌了`*revel.Controller`类型的结构,如: type AppController str ...

  9. PHP——大话PHP设计模式——SPL数据结构

  10. Android——自定义视图(一)转

    首先,建立一个Android工程,命名MyView. 然后,自定义一个类myView,继承View类.代码如下 package com.android.randy.viewDemo; import a ...