C++ 插入排序算法的实现与改进(含笔试面试题)

      插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

简单小tips:假设一个数列:1、2、5、3。插入排序的思想就是从1开始每次向前遍历:

2比1大,为有序

5比2大,5比1大,为有序

3比5小,无序,交换,交换之后3与2比,3与1比有序

结果为 :1、2、3、5


算法步骤:

1)将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

2)从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

实现代码:重载插入排序的函数,一次的改进:二分法查找插入位置

/***************************************************************************
 *  @file       main.cpp
 *  @author     MISAYAONE
 *  @date       24  March 2017
 *  @remark     24  March 2017 
 *  @theme      Insertion Sort 
 ***************************************************************************/

#include <iostream>
#include <vector>
using namespace std;

//传入一对迭代器,标准的插入排序
void Insertion_sort(vector<int>::iterator begin,vector<int>::iterator end)
{
	for (auto p1 = begin; p1 != end; ++p1)
	{
		auto p2 = p1;
		while ((p2 != begin) && *(p2-1)>*p2)
		{
			int temp = *(p2);
			*p2 = *(p2-1);
			*(p2-1) = temp;
			--p2;
		}
	}
}

//对函数进行重载,传入指向数组的指针和数组大小,同时进行第一次改进(也称二分插入排序)
void Insertion_sort(int a[],size_t size)
{
	for (size_t i = 1; i != size; ++i)
	{
		int low  = 0;//排好元素的下界
		int high = i;//排好元素的上界
		if (a[i-1] > a[i])//判断元素是否需要排序,满足条件则需要排序
		{
			int temp = a[i];//待排元素
			a[i] = a[i-1];//直接先将排好元素中的最后一个元素后移一位
			//while循环使用二分法找到插入位置
			while (low <= high)
			{
				int mid = (low+high)/2;
				if (temp < a[mid])//待排元素之前的序列肯定是有序的,找到其中位数比较大小
				{
					high = mid-1;			
				}
				else
					low = mid+1;		
			}
			size_t j=i-1;
			for(j;j>=high+1;j--)//移动元素
				a[j+1]=a[j];  
			a[j+1] = temp; 
		}
	}
}


int main(int argc, char **argv)
{
	int a[10] = {2,5,6,3,1,4,8,7,9,0};
	vector<int> vec(a,a+10);

	Insertion_sort(vec.begin(),vec.end());
	for (size_t i = 0; i < vec.size(); ++i)
	{
		cout<<vec[i]<<" ";
	}

	Insertion_sort(a,10);
	cout<<endl;
	for (size_t i = 0; i < 10; ++i)
	{
		cout<<a[i]<<" ";
	}

	cin.get();
	return 0;
}

复杂度分析:

最优时间复杂度:当输入数组就是排好序的时候,复杂度为O(n),而快速排序在这种情况下会产生O(n^2)的复杂度。
最差时间复杂度:当输入数组为倒序时,复杂度为O(n^2)

插入排序比较适合用于“少量元素的数组”

插入排序的复杂度和逆序对的个数一样,当数组倒序时,逆序对的个数为n(n-1)/2,因此插入排序复杂度为O(n^2)。


特点分析:稳定算法(stable)、in place算法


例题1:请写出链表的插入排序程序:

template<typename T>  
struct list_node  
{  
    struct list_node<T> *next;  
    T value;  
};  
template<typename T>  
struct _list  
{  
    struct list_node<T> *head;  
    int size;  
};  
template<typename T>  
void SortLink(struct _list<T> * link) {  
    struct list_node<T> *pHead,*pRear,*p,*tp;  
    if (!link) return;  
    for (pHead=link->head,pRear=0;pHead;pHead=pHead->next) {  
        for (tp=pHead,p=pHead->next;p;tp=p,p=p->next)  
            if (pHead->value>=p->value)  
                tp->next=p->next,p->next=pHead,pHead=p,p=tp;  
        if (!pRear) link->head=pHead;  
        else pRear->next=pHead;  
        pRear=pHead;  
    }  
}  

    原文作者:排序算法
    原文地址: https://blog.csdn.net/misayaaaaa/article/details/65662522
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞