插入排序与越界处理

来源:互联网 发布:淘宝新品上架的微淘 编辑:程序博客网 时间:2024/04/30 23:28

        插入排序的原理很简单,依次从序列中选取未排序的元素,插入到排序去即可。因此随意的写了第一个算法:

      

#ifndef Insert_Sort_H#define Insert_Sort_H#include <algorithm>#include <iostream>template <typename Type>bool Bigger(const Type* lhs,const Type* rhs){return *lhs>*rhs;}template <typename Type>bool Smaller(const Type* lhs,const Type* rhs){return *lhs<*rhs;}template <typename Type>void Insert_Sort(Type* first,Type* last,bool (*Comp)(const Type*,const Type*)=Bigger<Type>){if(++first==last)return;--first;Type* next=first;while(++next!=last){Type value=*next;Type* position=next;while(Comp(--position,next));++position;copy_backward(position,next,next+1);*position=value;}}#endif


        这里的构想是传入两个函数指针,从而实现升序和降序排列,在测试的过程中,升序排列完全没有问题,但降序去出现了不可预知的数。关键问题在于未定义的区域其值是一个无穷小的数,采用降序排列时,由于越界的问题,将这些数带入到了排序去内,因而产生了未知的数,其结果未必正确。但对于升序排列而言,必然存在这个无穷小的数要小于任一序列内的数,因此不会出现问题,即相当于默认条件position!=first-1,从而阻止了一定程度上的越界问题。对程序做如下更改:

#ifndef Insert_Sort_H#define Insert_Sort_H#include <algorithm>#include <iostream>template <typename Type>bool Bigger(const Type* lhs,const Type* rhs){return *lhs>*rhs;}template <typename Type>bool Smaller(const Type* lhs,const Type* rhs){return *lhs<*rhs;}//说明这里存在越界,已经解决,但存在其他问题,如果是非连续式存储,则first-1就没有定义了template <typename Type>void Insert_Sort(Type* first,Type* last,bool (*Comp)(const Type*,const Type*)=Bigger<Type>){if(++first==last)return;--first;Type* next=first;while(++next!=last){Type value=*next;Type* position=next;while(Comp(--position,next)&&position!=first-1);++position;copy_backward(position,next,next+1);*position=value;for(Type* iter=first;iter!=last;++iter)cout<<*iter<<' ';cout<<endl;}}#endif


        这样之后,程序就可以正常的工作啦~但并不是很好,因为程序中仍然出现越界的地方,如果是非连续存储的话,则很有可能出现访问未定义的元素问题.

        因此,调整程序,确保每一个操作都在序列之内:

       

#ifndef InsertSort_H#define InsertSort_H#include <algorithm>template <typename Type>bool Bigger(const Type* lhs,const Type* rhs){return *lhs>*rhs;}template <typename Type>bool Smaller(const Type* lhs,const Type* rhs){return *lhs<*rhs;}template <typename Type>void InsertSort(Type* first,Type* last,bool (*Func)(const Type*,const Type*)=Bigger){//空的序列,不需要排序if(first==last)return;for(Type* index=first+1;index!=last;++index){Type value=*index;//默认升序排序,如果待插入元素小于排序区第一个元素,则插入到最前面if(Func(first,index)){copy_backward(first,index,index+1);*first=value;}else{Type* next=index;--next;//直到不出现逆序的对儿,此时last就指向插入位置while(Func(next,&value)){*index=*next;index=next;--next;}*index=value;}}}#endif


        可以看出,确保每一次操作都在序列之内,可以很方便的处理边界问题。STL源码内对边界的处理很值得研究和学习~

0 0
原创粉丝点击