資料結構學習(C++)——單連結串列(定義與實現) (轉)
節點類
#ifndef Node_H:namespace prefix = o ns = "urn:schemas--com::office" />
#define Node_H
template
{
public:
Type data;
Node
Node() : data(Type()), link(NULL) {}
Node(const Type &item) : data(item), link(NULL) {}
Node(const Type &item, Node
};
#endif
【說明】因為資料結構裡用到這個結構的地方太多了,如果用原書那種宣告友元的做法,那宣告不知道要比這個類的本身長多少。不如開放成員,事實上,這種結構只是C中的struct,除了為了方便初始化一下,不需要任何的方法,原書那是畫蛇添足。下面可以看到,連結串列的public部分沒有返回Node或者Node*的,所以,別的類不可能用這個開放的介面對連結串列中的節點操作。
【重要修改】原書的預設建構函式是這樣的Node() : data(NULL), link(NULL) {} 。我原來也是照著寫的,結果當我做擴充時發現這樣是不對的。當Type為結構而不是簡單型別(int、……),不能簡單賦NULL值。這樣做使得定義的模板只能用於很少的簡單型別。顯然,這裡應該Type的預設建構函式。 這也要求,用在這裡的類一定要有預設建構函式。在下面可以看到構造連結串列時,使用了這個預設建構函式。當然,這裡是約定帶表頭節點的連結串列,不帶頭節點的情況請大家自己思考。
【閒話】請不要對int *p = new int(1);這種語法有什麼懷疑,實際上int也可以看成一種class。
單連結串列類
#ifndef List_H
#define List_H
#ifndef TURE
#define TURE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
typedef int BOOL;
#include "Node.h"
template
{
//基本上無引數的成員函式操作的都是當前節點,即current指的節點
//認為表中“第1個節點”是第0個節點,請注意,即表長為1時,最後一個節點是第0個節點
public:
List() { first = current = last = new Node
~List() { MakeEmpty(); delete first; }
void MakeEmpty() //置空表
{
Node
while (first->link != NULL)
{
q = first->link;
first->link = q->link;
delete q;
}
Initialize();
}
BOOL IsEmpty()
{
if (first->link == NULL)
{
Initialize();
return TURE;
}
else return FALSE;
}
int Length() const //計算帶表頭節點的單連結串列長度
{
Node
int count = 0;
while (p != NULL)
{
p = p->link;
count++;
}
return count;
}
Type *Get()//返回當前節點的資料域的地址
{
if (current != NULL) return ¤t->data;
else return NULL;
}
BOOL Put(Type const &value)//改變當前節點的data,使其為value
{
if (current != NULL)
{
current->data = value;
return TURE;
}
else return FALSE;
}
Type *GetNext()//返回當前節點的下一個節點的資料域的地址,不改變current
{
if (current->link != NULL) return ¤t->link->data;
else return NULL;
}
Type *Next()//移動current到下一個節點,返回節點資料域的地址
{
if (current != NULL && current->link != NULL)
{
prior = current;
current = current->link;
return ¤t->data;
}
else
{
return NULL;
}
}
void Insert(const Type &value)//在當前節點的後面插入節點,不改變current
{
Node
current->link = p;
}
BOOL InsertBefore(const Type &value)//在當前節點的前面插入一節點,不改變current,改變prior
{
Node
if (prior != NULL)
{
p->link = current;
prior->link = p;
prior = p;
return TURE;
}
else return FALSE;
}
BOOL Locate(int i)//移動current到第i個節點
{
if (i <= -1) return FALSE;
current = first->link;
for (int j = 0; current != NULL && j < i; j++, current = current->link)
prior = current;
if (current != NULL) return TURE;
else return FALSE;
}
void First()//移動current到表頭
{
current = first;
prior = NULL;
}
void End()//移動current到表尾
{
if (last->link != NULL)
{
for ( ;current->link != NULL; current = current->link)
prior = current;
last = current;
}
current = last;
}
BOOL Find(const Type &value)//移動current到資料等於value的節點
{
if (IsEmpty()) return FALSE;
for (current = first->link, prior = first; current != NULL && current->data != value;
current = current->link)
prior = current;
if (current != NULL) return TURE;
else return FALSE;
}
BOOL Remove()//刪除當前節點,current指向下一個節點,如果current在表尾,後current = NULL
{
if (current != NULL && prior != NULL)
{
Node
prior->link = p->link;
current = p->link;
delete p;
return TURE;
}
else return FALSE;
}
BOOL RemoveAfter()//刪除當前節點的下一個節點,不改變current
{
if (current->link != NULL && current != NULL)
{
Node
current->link = p->link;
delete p;
return TURE;
}
else return FALSE;
}
friend ostream & operator << (ostream & strm, List
{
l.First();
while (l.current->link != NULL) st<< *l.Next() << " " ;
strm << endl;
l.First();
return strm;
}
protected:
/*主要是為了高效的入隊演算法所新增的。因為Insert(),Remove(),RemoveAfter()有可能改變last但沒有改變last所以這個演算法如果在public裡除非不使用這些,否則不正確。但是last除了在佇列中非常有用外,其他的時候很少用到,沒有必要為了這個用途而降低Insert(),Remove()的所以把這部分放到protected,實際上主要是為了給佇列繼承*/ void LastInsert(const Type &value)
{
Node
last->link = p;
last = p;
}
void Initialize()//當表為空表時使指標復位
{
current = last = first;
prior = NULL;
}
//這部分函式返回型別為Node
Node
{
return current;
}
Node
{
prior = current;
current = current->link;
return current;
}
Node
{
return current->link;
}
Node
{
return first;
}
Node
{
return last;
}
Node
{
return prior;
}
void PutLast(Node
{
last = p;
}
//這部分插入刪除函式不建立或刪除節點,是原位操作的介面
void Insert(Node
{
p->link = current->link;
current->link = p;
}
void InsertBefore(Node
{
p->link = current;
prior->link = p;
prior = p;
}
void LastInsert(Node
{
p->link = NULL;
last->link = p;
last = p;
}
Node
{
if (current != NULL && prior != NULL)
{
Node
prior->link = current->link;
current = current->link;
return p;
}
else return NULL;
}
Node
{
if (current->link != NULL && current != NULL)
{
Node
current->link = current->link->link;
return p;
}
else return NULL;
}
private:
List(const List
Node
};
#endif
【說明】我將原書的遊標類Iterator的功能放在了連結串列類中,遮蔽掉了返回值為Node以及Node*型別的介面,這樣的連結串列簡單、實用,擴充也很好。
【後記】在完成書後作業的時候,我發現了原書做法的好處,也就是我的做法的不足。如果使用原書的定義,在完成一個功能時,只需要寫出對應的函式實現。而在我的定義中,必須先派生一個類,然後把這個功能作為成員或者友元。但是這種比較並不說明書上的定義比我的要合理。首先,使用到原位操作的情況並不多,書後作業只是一種特殊情況;換句話說,書上的定義只是對完成書後作業更實用些。其次,在使用到連結串列的時候,通常只會用到插入、刪除、取資料、搜尋等很少的幾個功能,我的定義足夠用了。而在完成一個時,對連結串列的擴充功能在設計階段就很清晰了,這時可以派生一個新類在整個軟體中使用,對整體的規劃更為有利。而對於單個連結串列的操作,把它作為成員函式更好理解一些。也就是說我的定義靈活性不差。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-988552/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 資料結構 - 單連結串列 C++ 實現資料結構C++
- 資料結構——單連結串列的C++實現資料結構C++
- js實現資料結構--單連結串列JS資料結構
- 【資料結構】連結串列(單連結串列實現+詳解+原碼)資料結構
- 資料結構和演算法——Go實現單連結串列並且反轉單連結串列資料結構演算法Go
- 資料結構學習--連結串列資料結構
- 資料結構-單連結串列、雙連結串列資料結構
- 演算法與資料結構-連結串列((linked-list)-Java實現單向連結串列演算法資料結構Java
- 資料結構之php實現單向連結串列資料結構PHP
- 資料結構-2.單向連結串列的實現資料結構
- 用c語言實現資料結構——單連結串列C語言資料結構
- 資料結構——單連結串列介面實現(C語言)資料結構C語言
- 資料結構--單連結串列(通過陣列實現)資料結構陣列
- 學習 JavaScript 資料結構(二)——連結串列JavaScript資料結構
- 資料結構與演算法學習-連結串列下資料結構演算法
- 資料結構與演算法學習-連結串列上資料結構演算法
- 資料結構實驗之連結串列五:單連結串列的拆分資料結構
- 資料結構練習題(順序表和單連結串列)C++資料結構C++
- 連結串列-單連結串列實現
- 【資料結構與演算法學習】線性表(順序表、單連結串列、雙向連結串列、迴圈連結串列)資料結構演算法
- 資料結構之單連結串列資料結構
- 資料結構04——單連結串列資料結構
- 資料結構之連結串列:206. 反轉連結串列資料結構
- 資料結構_連結串列的原理與應用1_單連結串列(基於C語言實現)資料結構C語言
- 6-C/C++實現資料結構連結串列相關操作C++資料結構
- 資料結構(雙向連結串列的實現)資料結構
- 資料結構-雙向連結串列(Python實現)資料結構Python
- php實現基本資料結構之連結串列PHP資料結構
- 資料結構與演算法——連結串列 Linked List(單連結串列、雙向連結串列、單向環形連結串列-Josephu 問題)資料結構演算法
- 資料結構--陣列、單向連結串列、雙向連結串列資料結構陣列
- java實現單連結串列、棧、佇列三種資料結構Java佇列資料結構
- 基本資料結構實現--單連結串列【含測試程式碼】資料結構
- 探索資料結構:單連結串列的實戰指南資料結構
- C++:用棧實現反轉連結串列,超簡單!C++
- C++資料結構連結串列的基本操作C++資料結構
- Redis資料結構—連結串列與字典Redis資料結構
- 資料結構之單連結串列的建立與刪除資料結構
- python演算法與資料結構-單連結串列(38)Python演算法資料結構
- 資料結構之連結串列篇(單連結串列的常見操作)資料結構