單鏈表的遍歷與優化


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(n 2)
時間復雜度太多效率低  所以需要改進
 
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 }
小結:
  • 單鏈表的遍歷需要在線性時間內完成
  • 在單鏈表的內部定義游標變量(指針),通過游標變量提高效率
  • 遍歷的函數需要相互依賴,相互的配合
  • 封裝節點的申請和刪除操作有利於增強擴展性


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM