内部排序算法1(插入排序)
重点指标
1. 排序算法的时间代价分析
2. 排序算法的空间代价分析
3. 排序方法的稳定性
4. 静态排序和动态排序
5. 算法的适用性
排序
1. 排序是对数据元素的逻辑顺序或者物理顺序的一种重新排列。
2. 排成非减(递增)顺序称为正序, 排成非增(递减)顺序称为逆序。
3. 排序的依据是排序码(可重复),即元素或记录中的用于作为排序依据的项。
4. 静态排序在排序过程中链表结构不变,可以避免数据移动,但是代价是增加了使用的指针空间。
排序算法的稳定性的判断原则
1. 如果需要把所有元素按排序的升序排列,在每趟从前向后比较选小时把排序码相等的视为更小者,或从后向前比较选大时把排序码相等的视为更大者,使得原本正序的元素视为逆序,一旦交换将导致两个排序码相等的元素发生相对位置的前后颠倒。
2. 在排序的过程中,需要以一个较大的间隔互换数据,或把数据隔空搬运一段较大距离时,排序方法一定不稳定,它可能会把原先排在前面的元素搬到具有相同排序码的另一个元素的后面,颠倒了具有相同排序码的不同元素的相对前后位置。
3. 不稳定的排序算法有4种:Shell排序、简单选择排序、快速排序和堆排序。
4. 稳定排序算法有 种,直接插入排序、折半插入排序、气泡排序、归并排序、锦标赛排序和基数排序。
排序算法的适用于那种数据结构(顺序结构和单链表结构)
1. 适用于顺序表的排序方法有:直接插入排序、折半插入排序、希尔排序、气泡排序、快速排序、简单选择排序、堆排序、归并排序、计数排序和奇偶排序等。
2. 适用于单链表的排序方法有:直接插入排序、气泡排序、简单选择排序、归并排序和基数排序。
3. 适用于树形排序的排序方法有:锦标赛排序(胜者树)、多路归并排序(败者树)、 二叉查找树排序、堆排序等。
排序算法的介绍
1. 插入排序
思路
将待排序的子序列中的一个元素按其排序码的大小插入到已经排好序的有序子序列中的适当位置,使得有序子序列扩大一个元素。如此继续,直到待排序子序列中的所有元素取空并都插入到有序子序列。
思想
把数组a[n]中待排序的n个元素看成一个有序表和一个无序表,开始时有序表中只包含一个元素a[0],无序表中包含有n-1个元素a[1]~a[n-1]。排序过程中每次从无序表中退成第一个元素,把它插入到有序表中的适当位置,使之成为新的有序表,这样经过n-1次退出和插入后,无序表就变成空表了,有序表中就包含了所有的元素。
图示
图片来自: 几种基本的插入排序
算法描述
//插入排序头文件
#pragma once
#include<iostream>
typedef int DataType;
class InsertSort
{
public:
InsertSort(int length);
void create();
void sort();
void print();
private:
DataType *data;
int len;
};
InsertSort::InsertSort(int length)
{
len = length;
data = new DataType[len];
}
inline void InsertSort::create()
{
std::cout << "请输入要排序的序列: " << std::endl;
for (int i = 0; i < len; i++)
{
int temp;
std::cin >> temp;
data[i] = temp;
}
std::cout << "输入完毕" << std::endl;
}
inline void InsertSort::sort()
{
int i, j;
for (i = 1; i < len; i++)
{
if (data[i] < data[i - 1]) //当序列放生逆序的时候才插入,否则跳过。
{
int temp = data[i]; //记录需要排序的那个值,然后从后往前比较并移动数据。
for (j = i - 1; temp < data[j] && j >= 0; j--)
{
data[j + 1] = data[j];
}
data[j + 1] = temp;
}
}
}
inline void InsertSort::print()
{
for (int i = 0; i < len; i++)
{
std::cout << data[i] << " ";
}
std::cout << std::endl;
}
main文件
//插入排序main文件
using namespace std;
#include"InsertSort.h"
int main() {
InsertSort insertSort(10); //排序的序列中有十个元素
insertSort.create(); //输入十个数
insertSort.sort(); //排序
insertSort.print(); //输出序列
system("pause");
}
结果
算法分析
事件复杂度分析
每次在有序的子序列中从后往前寻找插入元素应该插入的位置。这种方式导致算法事件代价严重依赖于待排序的序列的初始排列。最好的情况下,当初始排列全部有序(从小到大)的情况下,每趟插入元素只需要和有序序列的最后一个元素作比较,并不需要移动,总的比较次数(KCN)为n-1次, 移动次数(RMN)为0次。 在最坏的情况下,即待排序元素的序列中所有元素已经从大到小排列(反序),若想将它们翻转过来,则第i个元素要和前面i-1个元素做比较,总的比较次数为1+2+…+(n-1) = (n-1)*n/2次。在每一次比较之后都需要移动一次,加上取出该元素和放入指定的位置两次,也就是 ∑ni=0(i