zoukankan      html  css  js  c++  java
  • 【指针】基于单向链表的list(待改进)

    Description:

     请实现以下基于单向链表的list类

    enum Error_code
    
    {
    
             success,
    
             underflow,
    
             overflow
    
    };
    
    template <class List_entry>
    
    struct Node
    
    {
    
             List_entry entry;
    
             Node<List_entry> *next;
    
    };
    
     
    
    template <class List_entry>
    
    class MyList
    
    {
    
    public:
    
             MyList();
    
             ~MyList();
    
             // 拷贝构造函数和赋值运算符重载,注意深拷贝与浅拷贝的差异
    
             MyList(const MyList<List_entry> &copy);
    
             void operator =(const MyList<List_entry> &copy);
    
     
    
             // 清空list
    
             void clear();
    
             // 判断list是否为空
    
             bool empty() const;
    
             // 判断list是否已满
    
             bool full() const;
    
             // 获取list的元素数量
    
             int size() const;
    
             // 在第position个位置插入值为entry的元素,如果position为0则插入在链表头,依次类推
    
             // 若position < 0 或者 position > count,则返回underflow
    
             Error_code insert(int position, const List_entry &entry);
    
             // 删除第position个位置的元素,并将该元素的值保存在entry中
    
             // 若position < 0 或者 position >= count,则返回underflow
    
             Error_code remove(int position, List_entry &entry);
    
             // 获取第position个位置的元素,保存在entry中
    
             // 若position < 0 或者 position >= count,则返回underflow
    
             Error_code retrieve(int position, List_entry &entry) const;
    
             // 将第position个位置的元素替换为entry
    
             // 若position < 0 或者 position >= count,则返回underflow
    
             Error_code replace(int position, const List_entry &entry);
    
             // 用visit函数遍历list内所有的元素
    
             void traverse(void (*visit)(List_entry &));
    
    protected:
    
             int count;                                                                          // 记录list内元素数量
    
             Node<List_entry> *head;                                         // 链表头指针
    
             mutable int curPosition;                                   // current指针的位置编号
    
             mutable Node<List_entry> *current;                 // current指针
    
     
    
             // 设置current指针的位置,指向第position个位置
    
             void setPosition(int position) const;
    
    };
    View Code


     

    解题思路:

    首先,对于一个普通的list来说,最基本的不外乎增删查改,其他的赋值或清空都可以通过这4种操作来完成,写好这主要的4个函数就好了。

    另外,注意到这个MyList类提供了current这个指针。

    1.insert(增):

      position合理的情况下,若position为队头,则直接将position的next指向head,head再更新;

          若position不是队头,position的next指向下一个位置,前一个节点的next指向position;

    2.remove(删):

     position合理的情况下,若删除位置为队头,head=head->next,并注意将原本的队头delete;

             若删除位置不是队头,则前节点直接指向potision的后节点,position节点delete即可;

    3.retrieve(查):

          调用setPosition来查找目标,并返回值即可;

    4.replace(改):

          调用setPosition查找目标,并修改值;

    5.赋值运算:

        不断从copy中读取(retrieve),并插入(insert)到MyList中;

    6.clear(清空):

      可以不断调用remove来清空,这里代码我就直接用for循环来删除啦。

    7.setPosition:是通过current指针来提高平均时间复杂度的一个函数;

            当position比current大时,current只需向后更新;

            若position小于current时,则current先更新为head,然后再更新到position位置

    实现代码:

    enum Error_code//错误信息
    {
      success,
      underflow,
      overflow
    };
    
    template<class List_entry>
    struct Node
    {
      List_entry entry;
      Node<List_entry>*next;
    };
    
    template<class List_entry>
    class MyList
    {
      public:
         MyList() {
           curPosition = count = 0;
           head = current = 0;
         }
           
         ~MyList() {
           clear();
         }
    
         // 拷贝构造函数和赋值运算符重载
         MyList(const MyList<List_entry> &copy) {
          curPosition = count = 0;//拷贝构造函数一定要对数据成员进行初始化!
          head = current = 0;
              *this = copy;
         }
         void operator=(const MyList<List_entry> &copy) {
              clear();
              List_entry entry;
              for (count = 0; count < copy.size(); ) {
                  copy.retrieve(count, entry);//读取
                  insert(count, entry);       //增加
              }
              setPosition(copy.curPosition);
         }
    
          // 清空list
         void clear() {
             Node<List_entry>* tmp1 = head;
             Node<List_entry>* tmp2;
             while (tmp1 != 0) {
             tmp2 = tmp1->next;
                 delete tmp1;
             tmp1 = tmp2;
             }
             count = curPosition = 0;
             current = head = 0;
         }
        // 判断list是否为空
         bool empty() const {
              if (count == 0)
                 return true;
              else
                 return false;
         }
         // 判断list是否已满
         bool full() const {
              return false;
         }
            // 获取list的元素数量
         int size() const {
              return count;
         }
    
         // 在第position个位置插入值为entry的元素,如果position为0则插入在链表头,依次类推
             // 若position < 0 或者 position > count,则返回underflow
         Error_code insert(int position, const List_entry& entry) {//
                    if (position < 0 || position > count)
                        return underflow;
                    else
                    {
                      count++;
                      Node<List_entry>* tmp = new Node<List_entry>;
                      tmp->entry = entry;
                      if (position == 0) {
                           if (head == 0) {//在队头增加
                              tmp->next = head;
                              head = tmp;
                            }
                           current = head;
                       } else {         //在list中间增加
                         setPosition(position-1);
                         tmp->next = current->next;
                         current->next = tmp;
                         current = tmp;
                         curPosition++;
                       }
                    }
                  return success;
          }
    
          // 删除第position个位置的元素,并将该元素的值保存在entry中
             // 若position < 0 或者 position >= count,则返回underflow
         Error_code remove(int position, List_entry &entry) {
            if (position < 0 || position >= count)
                       return underflow;
                     else {
                       count--;
                       if (position == 0) //删队头
                          {
                            Node<List_entry>* tmp= head;
                entry = tmp->entry;
                            head= head->next;
                            delete tmp;
                            current = head;
                            curPosition = 0;
                        } else {         //删除list中的元素
                          setPosition(position-1);
                          Node<List_entry>* tmp = current->next;
                          entry = tmp->entry;
                          current->next = tmp->next;
                          delete tmp;
                          }
              return success;
                     }
         }
    
              // 获取第position个位置的元素,保存在entry中
             // 若position < 0 或者 position >= count,则返回underflow
         Error_code retrieve(int position, List_entry& entry) const {
            if (position < 0 || position >= count)
                       return underflow;
            else
            {
              setPosition(position);
                      entry = current->entry;
              return success;
            }
        }
    
        // 将第position个位置的元素替换为entry
             // 若position < 0 或者 position >= count,则返回underflow
         Error_code replace(int position, const List_entry &entry) {
            if (position < 0 || position >= count)
                return underflow;
            else
            {
              setPosition(position);
              current->entry = entry;
            return success;
            }
        }
         // 用visit函数遍历list内所有的元素
         void traverse(void(*visit)(List_entry&)) {
             Node<List_entry>* tmp = head;
             for (int i = 0; i < count; i++) {
                 (*visit)(tmp->entry);
                 tmp = tmp ->next;
             }
         }
      protected:
         int count; // 记录list内元素数量
         Node<List_entry>*head;  // 链表头指针
         mutable int curPosition;  // current指针的位置编号
         mutable Node<List_entry>* current;    // current指针
        // 设置current指针的位置,指向第position个位置
         void setPosition(int position) const {
              if (position >= curPosition)
                 for (; curPosition < position; curPosition++)
                      current = current->next;
              else
                 for (current = head, curPosition = 0; curPosition < position; curPosition++)
                     current = current->next;
         }
    };     
    View Code


    进一步思考:

    这里,我们不妨再看看,常常runtime error让我们头疼的链表问题是非法访问内存地址,

    比如,队列为空时,head==0,但我们常常不小心访问了head->next,或者企图访问head的前节点

    而这个情况常常发生在增删的情况中,那我们可以使list初始情况就为非空

    令head永远指向一个空节点node(node->next=0),初始情况curPosition=-1,

    这样每次插入新元素,不管新元素的位置在哪里,都不用再做特殊判断,直接更新position前节点的next即可

    也就是插入新元素只有以下这两种情况:

             和                  

    而这两种情况的实现代码都是:setPosition(position-1);

                  tmp->next = current->next;

                  current->next = tmp;

    每次删除新元素,也不用管是不是队头,直接更新前节点的next即可

    也就是删除新元素只有以下这两种情况:

     而这两种情况的实现代码都是:Node<List_entry>* tmp = current->next; 

                   current->next = tmp->next;

                  delete tmp;

    实现代码:

    /*有空队头的情况*/
    enum Error_code//错误信息
    {
      success,
      underflow,
      overflow
    };
    
    template<class List_entry>
    struct Node
    {
      List_entry entry;
      Node<List_entry>*next;
    };
    
    template<class List_entry>
    class MyList
    {
      public:
         MyList() {
            count = 0;
        curPosition = -1;
        head = current = new Node<List_entry>;
        head->next = 0;
         }
    
         ~MyList() {
        clear();
        delete head;
        head = current = 0;
        count = curPosition = 0;
         }
         // 拷贝构造函数和赋值运算符重载
         MyList(const MyList<List_entry> &copy) {
              count = 0;//拷贝构造函数一定要对数据成员进行初始化!
              curPosition = -1;
              head = current = new Node<List_entry>;
              head->next = 0;
              *this = copy;
        }
    
         void operator=(const MyList<List_entry> &copy) {
              clear();
              List_entry entry;
          while(count < copy.size()) {
            copy.retrieve(count, entry);//读取
                insert(count, entry);//增加
          }
          setPosition(copy.curPosition);
        }
          // 清空list
        void clear() {
             Node<List_entry>* tmp1 = head->next;
             Node<List_entry>* tmp2;
             while (tmp1 != 0) {
             tmp2 = tmp1->next;
                 delete tmp1;
             tmp1 = tmp2;
             }
             count = 0;
             current = head;
         head->next = 0;
         curPosition = -1;
         }
        // 判断list是否为空
         bool empty() const {
              if (count == 0)
                 return true;
              else
                 return false;
         }
         // 判断list是否已满
         bool full() const {
              return false;
         }
            // 获取list的元素数量
         int size() const {
              return count;
         }
         // 在第position个位置插入值为entry的元素,如果position为0则插入在链表头,依次类推
             // 若position < 0 或者 position > count,则返回underflow
         Error_code insert(int position, const List_entry& entry) {
                    if (position < 0 || position > count)
                        return underflow;
                    else
                    {
                      Node<List_entry>* tmp = new Node<List_entry>;
                      tmp->entry = entry;
                      setPosition(position-1);
                      tmp->next = current->next;
                      current->next = tmp;
                      current = tmp;
                      curPosition++;
                      count++;
                    }
                  return success;
          }
          // 删除第position个位置的元素,并将该元素的值保存在entry中
             // 若position < 0 或者 position >= count,则返回underflow
         Error_code remove(int position, List_entry &entry) {
            if (position < 0 || position >= count)
                       return underflow;
                     else {
               setPosition(position-1);
                       Node<List_entry>* tmp = current->next;
                       entry = tmp->entry;
                       current->next = tmp->next;
                       delete tmp;
                       count--;
               return success;
                     }
         }
              // 获取第position个位置的元素,保存在entry中
             // 若position < 0 或者 position >= count,则返回underflow
         Error_code retrieve(int position, List_entry& entry) const {
            if (position < 0 || position >= count)
                       return underflow;
            else
            {
              setPosition(position);
                      entry = current->entry;
              return success;
            }
        }
        // 将第position个位置的元素替换为entry
             // 若position < 0 或者 position >= count,则返回underflow
         Error_code replace(int position, const List_entry &entry) {
            if (position < 0 || position >= count)
                return underflow;
            else
            {
              setPosition(position);
              current->entry = entry;
            return success;
            }
        }
         // 用visit函数遍历list内所有的元素
         void traverse(void(*visit)(List_entry&)) {
             Node<List_entry>* tmp = head->next;
             for (int i = 0; i < count; i++) {
                 (*visit)(tmp->entry);
                 tmp = tmp ->next;
             }
         }
    
      protected:
         int count;// 记录list内元素数量
         Node<List_entry>*head;// 链表头指针
         mutable int curPosition;// current指针的位置编号
         mutable Node<List_entry>* current;// current指针
        // 设置current指针的位置,指向第position个位置
         void setPosition(int position) const {  
              if (position >= curPosition)
                 for (; curPosition < position; curPosition++)
                      current = current->next;
              else
                 for (current = head, curPosition = -1; curPosition < position; curPosition++)
                     current = current->next;
         }
    };
    View Code

    总结:

    也许你觉得这不过是少了十几行代码,少了两段if语句,但下一篇,双向链表,我们能更进一步看见这种方法的安全性和便捷性。

  • 相关阅读:
    单例模式
    pandas to_html
    restful
    numpy版本查看以及升降
    视频下载
    转载:caffe中的Reshape层
    caffe编译报错解决
    python 版Faster Rcnn
    转载:动态规划以及路径记录
    TensorFlow设置GPU占用量
  • 原文地址:https://www.cnblogs.com/zengyh-1900/p/4067679.html
Copyright © 2011-2022 走看看