您好,登錄后才能下訂單哦!
廣義表是一種數據結構,是線性表的推廣。也有人稱之為列表(lists)。廣泛的用于人工智能等領域的表處理結構。
對于廣義表,我們需要了解它的結構,通過學習廣義表,也加深了對遞歸的了解。整個廣義表都是了利用遞歸的特性實現的。
(一)首先我們要確定表中每個節點的結構,因為在廣義表中有三種不同結構的節點,我們可以使用枚舉enum列出我們所用到的結構節點類型。
enum Type { HEAD, SUB, VALUE };
(二)有了type類型,只要定義一個type類型的一個對象就可以輕松定義不同類型的節點。
struct GeneralizedNode { Type _type; union { int _value; GeneralizedNode* _SubLink; }; GeneralizedNode* _next; GeneralizedNode(Type type) { if (type == HEAD) { _type = HEAD; _next = NULL; } else if (type == VALUE) { _type = VALUE; _value = 0; _next = NULL; } else { _type = SUB; _SubLink = NULL; _next = NULL; } } };
我們可以看到一個廣義表節點的結構就定義出來了。對于HEAD類型的節點不需要_value和_SubLink這兩個數據成員,但是VALUE類型的節點需要_value,而SUB類型需要_SubLink。所以可以使用聯合union來把_value和_SubLink放在同一塊內存,以節省空間。
(三)有了節點的結構,下面就開始定義廣義表的框架。
對于廣義表,我們在意的是廣義表的結構,也就是說我們實現構造,拷貝構造,賦值重載,打印表,析構等函數即可。
class GeneralizedList { public: GeneralizedList(const char* str); GeneralizedList(); ~GeneralizedList(); GeneralizedList(const GeneralizedList& g); GeneralizedList operator=(GeneralizedList g); size_t Size();//表中數據的個數 size_t Deepth();//表的深度 void Print();//打印表 private: size_t _Size(GeneralizedNode* head); size_t _Deepth(GeneralizedNode* head); bool _IsValue(const char& c); GeneralizedNode* _CreatList(const char*& str); void _Print(GeneralizedNode* head); GeneralizedNode* _Copy(GeneralizedNode* head); void _Release(GeneralizedNode* head); private: GeneralizedNode* _head; };
其實廣義表的結構并不難,也就是一個主表上鏈了一些子表。在這里我們可以把子表看作是一個主表,利用遞歸的特性,達到分治的效果。這樣實現起來會非常的好理解。
要使用遞歸就不能使用公有成員函數,因為我們需要一個變量來控制遞歸的開始和結束。顯然一個私有成員變量_head是不能實現的,所以我們要定義一些內部私有函數來實現公有函數的功能,
GeneralizedList::GeneralizedList(const char* str) { _head = _CreatList(str); } GeneralizedList::GeneralizedList() :_head(NULL) { } GeneralizedList::~GeneralizedList() { _Release(_head); } GeneralizedList::GeneralizedList(const GeneralizedList& g) { _head = _Copy(g._head); } GeneralizedList GeneralizedList::operator = (GeneralizedList g)//不能加const和& { //if (this != &g) //{ // GeneralizedNode* tmp = _Copy(g._head); // _Release(_head); // _head = tmp; //} //return *this swap(_head, g._head);//現代寫法 return *this; } void GeneralizedList::Print() { _Print(_head); } size_t GeneralizedList::Size() { return _Size(_head); } size_t GeneralizedList::Deepth() { return _Deepth(_head); }
可以看到我們通過間接調用私有方法,不僅利用了類的封裝的特性,還控制了遞歸的層數。
(四)下面是私有方法的實現。
void GeneralizedList::_Release(GeneralizedNode* head) { GeneralizedNode* cur = head; while (cur) { GeneralizedNode* del = cur; cur = cur->_next; if (del->_type == SUB) { _Release(del->_SubLink); } delete del; } } bool GeneralizedList::_IsValue(const char& c) { if (c >= '1'&&c <= '9' || c >= 'a'&&c <= 'z' || c >= 'A'&& c <= 'Z') { return true; } return false; } GeneralizedNode* GeneralizedList::_CreatList(const char*& str) { assert(*str == '('); ++str; GeneralizedNode* newhead = new GeneralizedNode(HEAD);//biaozhi GeneralizedNode* cur = newhead; while (*str) { if (_IsValue(*str)) { GeneralizedNode* tmp = new GeneralizedNode(VALUE); tmp->_value = *str; cur->_next = tmp; cur = cur->_next; str++; } else if (*str == '(') { GeneralizedNode * subNode = new GeneralizedNode(SUB); cur->_next = subNode; cur = cur->_next; subNode->_SubLink = _CreatList(str); //如果是'('說明后面是一個子表,我們遞歸的創建子表, 然后返回子表的頭指針,將頭指針鏈到主表上 } else if (*str == ')') { str++; return newhead; } else { ++str; } } assert(false); return _head; } void GeneralizedList::_Print(GeneralizedNode* head) { GeneralizedNode* cur = head; while (cur) { if (cur->_type == HEAD) { cout << '('; } else if (cur->_type == VALUE) { cout << cur->_value; if (cur->_next)//不為NULL打印',',防止在最后一個值后面打印一個',' { cout << ','; } } else { _Print(cur->_SubLink); if (cur->_next)//(1,2,(3,4))cur為空,不打印',' { cout << ','; } } cur = cur->_next; } cout << ')'; } size_t GeneralizedList::_Size(GeneralizedNode* head) { GeneralizedNode* cur = head; size_t size = 0; while (cur) { if (cur->_type == VALUE) { size++; } else if (cur->_type==SUB) { size +=_Size(cur->_SubLink); } cur = cur->_next; } return size; } size_t GeneralizedList::_Deepth(GeneralizedNode* head) { GeneralizedNode* cur = head; size_t maxDeep = 1; while (cur) { if (cur->_type == SUB) { size_t deep = _Deepth(cur->_SubLink); //最深的一層子表返回1, // 每返回一層deep就會+1; if (deep + 1 > maxDeep) { maxDeep = deep + 1; } } cur = cur->_next; } return maxDeep; } GeneralizedNode* GeneralizedList::_Copy(GeneralizedNode* head) { GeneralizedNode* cur = head->_next; GeneralizedNode* newHead = new GeneralizedNode(HEAD); GeneralizedNode* newCur = newHead; while (cur) { if (cur->_type == VALUE) { newCur->_next = new GeneralizedNode(VALUE); newCur = newCur->_next; newCur->_value = cur->_value; } else if (cur->_type == SUB) { newCur->_next = new GeneralizedNode(SUB); newCur = newCur->_next; newCur->_SubLink = _Copy(cur->_SubLink); //如果是子表節點, //就遞歸拷貝子表,將子表的頭節點返回鏈接到SUB節點上, //通過SubLink可以找到子表 } cur = cur->_next; } newCur = NULL; return newHead; }
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。