廣義表

    廣義表作爲數據結構的一種,是區別於順序表的一種數據結構,思想需要使用遞歸來實現。

   實現廣義表的節點(generaaLizedNode)

enum Type
{
	HEAD,
	VALUE,
	SUB,
};


struct generaalizedNode
{
	generaalizedNode(Type type = HEAD, char value = 0)
	      :_Type(type)
	      , _next(NULL)
	{
		if (_Type == VALUE)
		{
			_value = value;
		}
		else if (_Type == SUB)
		{
			_subLink = NULL;
		}
	}

	Type _Type;
	generaalizedNode* _next;

	union   //節省空間
	{
		char _value;
		generaalizedNode* _subLink;
	};
};

1.實現構造一個廣義表,在構造函數中不能使用遞歸,所以寫一個保護域的函數完成功能。

       generaalized(const char* str)
		:_head(NULL)
	{
		_head = _createNode(str);
	}       bool _isvalue(const char ch)
	{
		if ((ch >= '0'&&ch < '9') || (ch >= 'a'&&ch < 'z')
			|| (ch >= 'A'&& ch < 'Z'))
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	generaalizedNode* _createNode(const char*& str)
	{
		if (*str == '(')
		{
			++str;
		}

		generaalizedNode* head = new generaalizedNode(HEAD);
		generaalizedNode* cur = head;

		while (*str)
		{
			if (_isvalue(*str))
			{
				cur->_next = new generaalizedNode(VALUE, *str);
				cur = cur->_next;
				++str;
			}
			else if (*str == '(')
			{
				generaalizedNode* subNode = new generaalizedNode(SUB);
				cur->_next = subNode;
				cur = cur->_next;

				subNode->_subLink = _createNode(str);
				//++str;
			}
			else if (*str == ')')
			{
				++str;
				return head;
			}
			else
			{
				++str;
			}
		}
		cout << "false" << endl;
		assert(false);
		return head;
	}
	2.打印廣義表
       void print()
	{
		_print(_head);
		cout << endl;
	}        void _print(generaalizedNode* head)
	{
		if (head == NULL)
		{
			return;
		}
		generaalizedNode* cur = head;

		while (cur)
		{
			if (cur->_Type == HEAD)
			{
				cout << "(";
			}
			else if (cur->_Type == VALUE)
			{
				cout << cur->_value;
				if (cur->_next)
				{
					cout << ",";
				}
			}
			else if (cur->_Type == SUB)
			{
				_print(cur->_subLink);
				if (cur->_next)
				{
					cout << ",";
				}
			}
			cur = cur->_next;
		}
		cout << ')';
	}
	3.計算size
         size_t size()
	{
		return _size(_head);
	}


總結:

 1.使用到遞歸的地方把握兩點要求

   1).子問題

   2).遞歸返回條件

 2.就本例子而言,拿到一個字符串,創建廣義表的時候拿到單個字符,首先判斷他的類型,從而選擇不同的邏輯,例如,拿到是VALUE類型,就去創建一個VALUE類型的節點,將其鏈接到前面的節點的_next上,繼續往後遍歷字符串。同理,如果拿到的是SUB類型,創建一個SUB類型的節點,將其鏈接到前面的節點的_next上,同時需要遞歸進去穿件子問題的鏈。

  3.注意它的書寫 generaalizedNode* _createNode(const char*& str);,必須要加引用,否則遞歸進去會丟失數據,導致數據丟失,或者死循環。

 4.本人在學習的時候,自己畫的圖片,希望可以幫你們理解廣義表


wKioL1cU67uiiaLzAACIZT2bzQM552.png

wKiom1cU6v6iOHCNAAA5ckeJsIo132.png


ps:當然上述例子沒有實現析構函數,拷貝構造,賦值運算符的重載,是因爲本人在學習的時候是以廣義表的結構爲重點學習的。

   以上就是本人在學習過程中的一些經驗總結。當然,本人能力有限,難免會有紕漏,希望大家可以指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章