广义表作为数据结构的一种,是区别于顺序表的一种数据结构,思想需要使用递归来实现。

   实现广义表的节点(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:当然上述例子没有实现析构函数,拷贝构造,赋值运算符的重载,是因为本人在学习的时候是以广义表的结构为重点学习的。

   以上就是本人在学习过程中的一些经验总结。当然,本人能力有限,难免会有纰漏,希望大家可以指正。