C++版本直接插入排序

总体思想:将一个元素插入到已经排好序的有序表中,从而得到一个新的记录数增加1的有序表。
技巧是:

默认第一个元素是已经排好序的,后面的元素就是插入他的左边还是右边的问题,默认升序排列,比他小的插到左边,比他大的插到右边(实际上所有元素都在他右边,如果比他大就不交换即可)。


每一次比较都是将第i个元素和第i-1个元素比较,如果发现后面的元素小则表示需要将后面的元素插入到前面的有序表中,才会进行内层循环


内层循环从有序表的最后一个元素开始,往前遍历,直到遇到小于等于哨兵的元素时,停止循环,而之前遍历到的元素都需要进行向后移动,以挪出空位给哨兵(哨兵值就是当前需要插入到新位置的元素的值)。


设置一个哨兵,用来存放需要插入到新位置的元素(就是说这个元素比他前面的元素要小)。


1.外层循环从第二个元素开始(因为默认第一个元素已经排好队了)


2.只有当第i个元素比第i-1个元素小的时候才需要进行内层循环,表示将第i个元素插入到他应该位于的位置,需要在内层循环移动前面有序表里的元素,同时需要用到哨兵缓存当前元素。


3.外层循环遍历到最后一个元素(第n个元素,因有效数据的下标这里从1开始)以后,结束排序。


#include <iostream>
using namespace std;

#define MAXSIZE 100
typedef int Status;

#define OK  1
#define ERROR 0
#define TRUE  1
#define FALSE 0

template <typename T>
class SqList
{
public:
    T r[MAXSIZE+1];
    int length;
public:
    SqList(T * var,int len);
    SqList();
    void printList();

    Status swapElement(int i, int j);

    void InsertSort();
};

template <typename T>
SqList<T>::SqList(T * var,int len)
{
    length = len/sizeof(T);
    memcpy(&(r[1]), var, len);
}

template <typename T>
SqList<T>::SqList()
{
    memset(this, 0, sizeof(SqList));
}

template <typename T>
Status SqList<T>::swapElement(int i,int j)
{
    T tmp =this->r[i];
    this->r[i] = this->r[j];
    this->r[j] = tmp;
    return OK;
}

template <typename T>
void SqList<T>::printList()
{
    for (int i = 1; i <= length; i++)
    {
        cout << this->r[i] << "\t";
    }
    cout << endl;
}

/************************************************************************/
/* 直接插入排序                                                                     */
/************************************************************************/
template <typename T>
void SqList<T>::InsertSort()
{
    int i = 0, j = 0;
    for (i = 2; i <= length; i++)//外层循环表示从无序表中依次将其元素插入到有序表中
                                //默认第一个元素是有序表,所以从第二个元素开始直到第n个元素结束,
                                //这些元素都是无序表中的元素,需要依次把它们插入到前面的有序表中
                                //一次外层循环表示处理好无序表中的一个元素
    {
        if (r[i] < r[i - 1])//第i个元素是无序表中的第一个元素
                            //第i-1个元素是有序表中的最后一个元素,也是有序表中最大的元素
                            //如果无序表中的第一个元素(当前元素)比有序表中的最大元素小
                            //表示需要将当前元素往前插,至于插到什么位置,由内层循环决定
        {
            r[0] = r[i];//利用哨兵将当前元素的值缓存下来
            for (j = i - 1; r[j] > r[0]; j--)//内层循环将比当前元素的值(哨兵的值)大的元素后移挪出空位
            {
                r[j + 1] = r[j];//移动比哨兵大的元素
            }

            r[j + 1] = r[0];//将哨兵插入空位,该空位以前的元素要么为空要么逗比他小,否则不会结束循环
        }
    }//遍历到最后一个元素的时候排序完毕
}

int main(void)
{
    int myList[9] = {90,10,50,80,30,70,40,60,20};
    SqList<int> list(myList,sizeof(myList));

    cout << "before sort:"<< endl;
    list.printList();

    list.InsertSort();
    cout << "after sort:" << endl;
    list.printList();

    cout<<"Hello!"<<endl;
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值