zoukankan      html  css  js  c++  java
  • 单链表的遍历与优化

    1. 单链表存在的问题
    (1). 问题引入
    怎么样遍历单链表中的元素?
    (2). 原来单链表的遍历
    #include <iostream>
    #include "linklist.h"
     
    using namespace std;
    using namespace DTLib;
     
    int main()
    {
        LinkList<int> l;
     
        for(int i=0;i<6;i++)   //时间复杂度O(n)
        {
            l.insert(0,i);
        }
     
        for(int i=0;i<l.length();i++)//时间复杂度O(n)
        {
         cout<<l.get(i)<<endl;        //时间复杂度O(n)
        }
    }

     
     
    根据事件复杂度分析可知道遍历时的时间复杂度为了O(n2)
    时间复杂度太多效率低  所以需要改进
     
    2. 设计的思路
    (1) 在单链表内部定义一个游标( Node* m_current)
    (2) 遍历开始前将游标指向位置为0的数据元素
    (3) 获取游标指向的数据元素
    (4)  通过节点中的next指针移动游标
     
    • 增加的与遍历相关函数如下

     
    • 函数原型为

     //LinkList.h

      1 #ifndef LINKLIST_H
      2 #define LINKLIST_H
      3 #include "List.h"
      4 namespace DataStructureLib
      5 {
      6     template <typename T>
      7 
      8     class LinkList:public List<T>
      9     {
     10     protected:
     11         struct Node{
     12             T value;
     13             Node* next;
     14         };
     15 
     16         mutable Node m_header;//头结点 、mutable为了让get函数中的const属性导致的&m_header(编译器认为是要修改成员变量)mutable就允许const成员函数取地址
     17         int m_length;//链表的长度
     18 
     19         Node* position(int i) const//返回第i和元素的指针
     20         {
     21             Node* ret=&m_header;
     22 
     23             for(int p=0;p<i;p++)
     24             {
     25                 ret=ret->next;
     26             }
     27 
     28             return ret;//元素地址保存在该节点的next指针域中
     29         }
     30         
     31         //游标
     32         int m_step;
     33         Node* m_current ;
     34     public:
     35         LinkList()
     36         {
     37             m_header.next=NULL;
     38             m_length=0;
     39             m_step=1;
     40             m_current=NULL;
     41         }
     42         
     43         bool insert(int index, const T& elem)//思路:1.找到index位置处的元素;2.在该元素尾部insert新元素
     44         {
     45             bool ret=(index<=m_length)&&(index>=0);
     46 
     47             Node* NewNode=new Node ;
     48 
     49             if (ret)
     50             {
     51                 if (NULL!=NewNode)
     52                 {
     53                     NewNode->value=elem;
     54 
     55                     Node* indexNode=position(index);
     56                     NewNode->next=indexNode->next;
     57                     indexNode->next=NewNode;
     58 
     59                     m_length++;
     60                 }
     61                 else{
     62                     throw("has Not enougth memory to insert new element ...");
     63                 }
     64 
     65             }
     66             return ret;
     67         }
     68 
     69         bool remove(int index)
     70         {
     71             bool ret=((index<=m_length)&&(index>=0));
     72 
     73             if (ret)
     74             {
     75                 Node* CurrentNode=position(index);
     76                 Node* toDelNode=CurrentNode->next;
     77                 CurrentNode->next=toDelNode->next;
     78 
     79                 delete toDelNode ;
     80                 m_length--;
     81             }
     82 
     83             return ret;
     84         }
     85         
     86         bool set(int index,const T& e)
     87         {
     88             bool ret=((0<=index)&&(index<=m_length));
     89 
     90             if (ret)
     91             {
     92                 Node* CurrentNode=position(index);
     93                 CurrentNode->next->value=e;
     94             }
     95             
     96             return  ret; 
     97         }
     98 
     99         bool get(int index, T& elem) const
    100         {
    101             bool ret=((index<=m_length)&&(index>=0));
    102 
    103             if (ret)
    104             {
    105                 Node* CurrentNode=position(index);
    106                 elem= CurrentNode->next->value;
    107             }
    108 
    109             return ret;
    110         }
    111 
    112         T get(int index)
    113         {
    114             T ret;
    115             if((index<m_length)&&(0<=index))
    116             {
    117                 Node* CurrentNode=position(index);
    118                 ret= CurrentNode->next->value;
    119             }
    120 
    121             return ret; 
    122         }
    123         int getlength() const
    124         {
    125             return m_length;
    126 
    127         }
    128 
    129         void clear()
    130         {
    131                                 
    132             while (m_header.next)
    133             {
    134                 Node* toDelNode=m_header.next;
    135                 m_header.next=toDelNode->next;
    136                 delete toDelNode;
    137             }
    138             m_length=0;
    139         }
    140         
    141         //寻找e元素所在的位置,
    142         //返回值 失败:-1    成功:e元素所在的位置的id
    143         int find(T& e)
    144         { 
    145             int ret = -1;
    146             for (int i=0;i<m_length;i++)
    147             {
    148                 if (e==get(i))
    149                 {
    150                     ret=i;
    151                 }
    152             }
    153 
    154             return ret;
    155         }   
    156 
    157 
    158         bool move(int i,int step=1)//将游标定位到目标位置,//i代表目标位置  step游标每次移动的节点的数目
    159         {
    160             bool ret= (0<=i)&&(i<m_length)&&(step>0);
    161 
    162             if (ret)
    163             {
    164                 m_current=position(i)->next;
    165                 m_step=step;
    166             }
    167 
    168         return ret;
    169 
    170         }
    171 
    172         bool end()//游标有无到达链表尾部
    173         {
    174             return (m_current==NULL);
    175         }
    176 
    177         T current()//获取游标所指向的数据元素
    178         {
    179             if(!end())
    180             {
    181                 return  m_current->value ;
    182             }
    183             else
    184             {
    185                 throw("No Value at current position...");
    186             }
    187         }
    188 
    189         //移动游标  相当于每次移动的大小m_step
    190         bool next()
    191         {
    192 
    193             int i=0;
    194 
    195             while ((m_step>i)&&(!end()))
    196             {
    197                 m_current=m_current->next;
    198                 i++;
    199             }
    200 
    201             return (i==m_step);
    202         }
    203         
    204         ~LinkList()
    205         {
    206             clear();
    207         }
    208 };
    209 
    210 }
    211 #endif

    测试:

     1 #include<iostream>
     2 #include "object.h"
     3 #include "SeqList.h"
     4 #include "LinkList.h"
     5 
     6 using namespace std;
     7 using namespace DataStructureLib;
     8 
     9 
    10 int main(int argc, char const *argv[])
    11 {
    12     LinkList<int> l;
    13 
    14     for(int i=0;i<6;i++)
    15     {
    16         l.insert(0,i);
    17     }
    18 
    19     for(l.move(0,1);(!l.end());l.next())
    20     {
    21         cout<<l.current()<<endl;
    22     }
    23     system("pause"); 
    24     return 0;
    25 }
    小结:
    • 单链表的遍历需要在线性时间内完成
    • 在单链表的内部定义游标变量(指针),通过游标变量提高效率
    • 遍历的函数需要相互依赖,相互的配合
    • 封装节点的申请和删除操作有利于增强扩展性
  • 相关阅读:
    script 标签的defer,async的作用,及拓展浏览器多线程,DOMContentLoaded
    vuex基本熟悉与使用
    关于h5屏幕适配
    react-router4.0的使用
    使用gulp 合并压缩打包,实时监控文件,实现本地server
    组件之间的通讯:vuex状态管理,state,getters,mutations,actons的简单使用(一)
    vue怎么样创建组件呢??
    基于ionic框架封装一个图片轮播指令的几点
    使用php在服务器端生成图文验证码(二)
    字符串与对象的相互转化
  • 原文地址:https://www.cnblogs.com/zhaobinyouth/p/9756786.html
Copyright © 2011-2022 走看看