插入排序和一点小感悟(c++版)

很早之前,为了应付数据结构考试。花了一星期多看了数据结构,当时觉得也没什么难的。

过了老久,总算是招报应了,做笔试题发现其实所有理解只是在表面,实际上我并不会实现,确实是这样,学术这东西真没捷径,还是要沉下心来才能有所见解。

看了清华慕课上邓老师的数据结构,决定自己跟着他的接口实现一下,于是也开始学c++,学了点语法,然后就开始实现了,说实话,真难。刚好今天写插入排序算法,所以也就记下来。

其实这是很简单的算法

好吧,废话不多说,插入排序,就是有一堆乱序的数据,如果要排好顺序,除了最直观的我们人最喜欢的选择排序外,应该就是插入排序了,从递归思路开始想,在排序过程中,一般我们都是分成排好的那一堆和还没排好的那一堆,我们在排序过程中,从没有排好的里面拿出最前面那个,然后找到排好那一堆里面的一个适当的位置,使得插入以后排好那一堆依然是有序的,于是排好的会一直增加,未排好的也会一直减退。保证了算法的有穷性。从迭代的思路当然是一开始,拿最开始那个,随便找个地方放上去,然后拿出下一个,比较如果大,就放在它后面,依次类推。

我c++的实现是这样的:

template<typename T>
void List<T>::insertionSort(Posi(T) p, int n)
{
    Posi(T) runner = p;
    p = p->next;
    for (int i = 1; i < n; i++)
    {
        
        int j = i+1;
        while (j-- > 0)
        {
            if ((p->data)>(runner->data)||p==header)
            {
                Posi(T) temp = p->next;
                this->insertAsNext(p, runner);
                runner = temp->pred;
                p = temp;
                break;
            }
            else
            {
                runner = runner->pred;
            }
        }
    }
}

我相信直接看,肯定有疑问,首先,我这个方法是链表LIst类的一个保护成员,Posi(T)是这样的:

#define Posi(T) ListNode<T>*

每个链表节点,邓老师用了链表节点部件,我的接口声明当然是取至邓老师的教材。(这里有必要提一下)

我想算法并没有什么好说的,但是我在定义这个算法的过程中,遇到了点问题,其实一开始我的while循环是这样的:

if ((p->data)<(runner->data))
            {
                runner = runner->pred;
            }
            else
            {
                Posi(T) temp = p->next;
                this->insertAsNext(p, runner);
                runner = temp->pred;
                p = temp;
                break;
                
            }

其实是一样的,但是有个漏洞就是,如果,准备插入的元素如果是有序部分的最小,那么它会比较到有序序列的前一个,在这个链表类里应该是header哨兵,隐患很显而易见,在这个情况下是无法正常排序的。

所以我考虑了两种解决方案:

         if ((p->data)<(runner->data)&&p!=header)
           {
                runner = runner->pred;
            }
            else
            {
                Posi(T) temp = p->next;
                this->insertAsNext(p, runner);
                runner = temp->pred;
                p = temp;
                break;
                
            }        

和我决定下一种:

if ((p->data)>(runner->data)||p==header)
            {
                Posi(T) temp = p->next;
                this->insertAsNext(p, runner);
                runner = temp->pred;
                p = temp;
                break;
            }
            else
            {
                runner = runner->pred;
            }

之后看了邓老师的实现方法:

天啊,竟然忘记接口定义的search函数。罪过罪过,太水了。

好吧那我定义一下search

template<typename T>
Posi(T) List<T>::search(T const& e, int n, Posi(T) p) const
{
    while (n-->0)
    {
        p = p->pred;
        if (p->data <= e)
        {
            return p;
        }
    }
    return header;
}

 书上版本:

原文地址:https://www.cnblogs.com/wuweixin/p/5333749.html