• 插入排序和一点小感悟(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;
    }

     书上版本:

  • 相关阅读:
    Mysql:Changes in MySQL 5.6.6 (2012-08-07, Milestone 9):Group-Commit等等:重大变化版本!
    Mysql:Changes in MySQL 5.6.9 (2012-12-11, Release Candidate):GTID-based variables have been 【renamed】
    Mysql:Changes in MySQL 5.6.13 (2013-07-31, General Availability):不再支持可能引起混乱的【选项缩略】写法!
    Mysql:Changes in MySQL 5.6.22 (2014-12-01, General Availability):【sql-log-bin】
    Mysql:Changes in MySQL 5.6.30 (2016-04-11, General Availability):--ssl-mode:
    Mysql:Changes in MySQL 5.6.34 (2016-10-12, General Availability):secure-file-priv
    Windows Linux子系统Windows 10安装指南
    WSL2-参考的对象类型不支持尝试的操作。
    Win10开启Hyper-V后无法运行VMware虚拟机的解决方法
    Kubernetes---高可用的 K8S 集群构建
  • 原文地址:https://www.cnblogs.com/wuweixin/p/5333749.html
Copyright © 2020-2023  润新知