C/C++泛型编程实现数据结构之广义表

C/C++泛型编程实现数据结构之广义表

广义表是线性表的推广,又称列表。线性表的元素只限于原子项,即每个数据元素只能是一个数或一个记录,如果放松对线性表元素的这种限制,允许他们自身具有结构,那么就产生了广义表。

广义表是一种多层次的线性结构,像是一颗倒扣的树,实际上,这也算是一种树形结构。广义表不仅是线性表的推广,也算是树结构的推广。

广义表的存储结构

广义表的元素本身可以具有结构,这是一种带有层次性的线性结构。这里我们定义了三个域。一个为tag标志位,指示了当前元素是原子还是子表。广义表规定了当tag为0时,当前原子项为原子(data),当tag为1时,当前原子项指向下一个原子子表的地址。(slink),即当广义表中的某个节点出现了data时,不可能出现节点slink。这个我们可以通过union联合体来实现。
另一个节点是link。link指向了同一层次的下一个元素的地址。类似于链表中得到next,link把每一个节点都窜通在了一起,不同于slink的是,link指向下一个节点,slink指向子表,当slink存在是,link一定为NULL。
存储结构

广义表的基本操作

  1. 建立广义表
  2. 输出广义表
  3. 查找广义表中元素
  4. 获取广义表中的tail尾表
  5. 获取广义表深度

广义表理论存储形式直观表述

存储结构直观表述

代码实现广义表结构

其中tag为标志位,data和slink在联合体中,link指向下一个节点,当节点是本层次最后一个元素时,link为NULL

typedef enum { atom, list }NodeTag;
template <typename DataType>
typedef struct GLNode{
		NodeTag tag;
		union {
			DataType data;
			GLNode* slink;
		};
		GLNode* link;
	}*Glist;

代码实现广义表建立

用户输入字符。若当前字符为左括号,则设当前tag为1(list),否则当前tag为0(atom),若用户输入为空格,则广义表为空表。由上图可知,广义表创建是一个递归的过程,所以这里使用递归来实现。当然如果表特别大对内存空间有很大压力,则我们可以使用栈来模拟递归操作。最后本函数结尾返回广义表头

Glist CreateGList(Glist GL) {
		char ch;
		ch = getchar();
		if (ch != ' ') {
			GL = (GLNode *)malloc(sizeof(GLNode));
			if (ch == '(') {
				GL->tag = list;
				GL->slink = CreateGList(GL->slink);
			}
			else {
				GL->tag = atom;
				GL->data = ch;
			}
		}
		else GL = NULL;
		ch = getchar();
		if (GL != NULL) {
			if (ch == ',')
				GL->link = CreateGList(GL->link);
			else
				GL->link = NULL;
			return GL;
		}		
	}

代码实现广义表输出操作

广义表输出也是一个递归的操作。这里我们先判断广义表的标志位tag。如果tag为list,则暗示当前节点指向了下一个子表的地址。那么我们使用递归来访问当前节点的子表的地址slink。当然如果slink为空,那么子表就是空表,自然就需要输出空格了。当前子表判断后,我们可以继而判断当前层次的下一个元素。如果link为空,则当前表结束。否则我们每当访问一个link,输出一个逗号,并递归的访问下一个元素的地址。输出。

void PrintGlist(Glist GL = this.GL) {
		if (GL != NULL) {
			if (GL->tag == list) {
				cout << "(";
				if (GL -> slink == NULL)cout << " ";
				else PrintGlist(GL->slink);
			}
			else {
				cout << GL->data;
			}
			if (GL->tag == list)cout << ")";
			if (GL->link != NULL) {
				cout << ",";
				PrintGlist(GL->link);
			}
		}
	}

广义表的查找操作

这段函数的作用时在广义表GL中查找值为X的原子,并且如果查找成功就令mark的值为1,很容易得出。这也是一个递归的过程。

void FindGlistX(GList GL,DataType x,int * mark) {
		if (GL != NULL) {
			if (GL->tag == 0 && GL->data == x) {
				p = GL;
				*mark = 1;
			}
			else {
				if (GL->tag == 1)FindGlistX(GL->slink, x, mark);
				FindGlistX(gl->link, x, mark);
			}
		}
	}

判断广义表深度

void depth(Glist GL, int * maxdh) {
		int h;
		if (GL->tag == 0)*maxdh = 0;
		else {
			if (GL->tag == 1 && GL->slink == NULL) {
				*maxdh = 1;
			}
			else {
				GL = GL->slink;
				*maxdh = 0;
				do {
					depth(GL, &h);
					if (h > *maxdh) {
						maxdh = h;
					}
				} while (GL != NULL);
				(*maxdh)++;
			}
		}
	}

完整代码

#include <iostream>
#include <string>
using namespace std;

typedef enum { atom, list }NodeTag;
template <typename DataType>
class GLIST {
private:
	typedef struct GLNode{
		NodeTag tag;
		union {
			DataType data;
			GLNode* slink;
		};
		GLNode* link;
	}*Glist;

public:
	Glist _GL;
	Glist p;

public:
	//建立广义表的存储结构
	Glist CreateGList(Glist GL) {
		char ch;
		ch = getchar();
		if (ch != ' ') {
			GL = (GLNode *)malloc(sizeof(GLNode));
			if (ch == '(') {
				GL->tag = list;
				GL->slink = CreateGList(GL->slink);
			}
			else {
				GL->tag = atom;
				GL->data = ch;
			}
		}
		else GL = NULL;
		ch = getchar();
		if (GL != NULL) {
			if (ch == ',')
				GL->link = CreateGList(GL->link);
			else
				GL->link = NULL;
			return GL;
		}		
	}

	void PrintGlist(Glist GL = this.GL) {
		if (GL != NULL) {
			if (GL->tag == list) {
				cout << "(";
				if (GL -> slink == NULL)cout << " ";
				else PrintGlist(GL->slink);
			}
			else {
				cout << GL->data;
			}
			if (GL->tag == list)cout << ")";
			if (GL->link != NULL) {
				cout << ",";
				PrintGlist(GL->link);
			}
		}
	}

	void FindGlistX(GList GL,DataType x,int * mark) {
		if (GL != NULL) {
			if (GL->tag == 0 && GL->data == x) {
				p = GL;
				*mark = 1;
			}
			else {
				if (GL->tag == 1)FindGlistX(GL->slink, x, mark);
				FindGlistX(gl->link, x, mark);
			}
		}
	}

	Glist tail() {
		Glist p;
		if (GL != NULL && GL->tag != 0) {
			p = GL->slink;
			p->link = NULL;
			return p;
		}
		else return NULL;
	}

	void depth(Glist GL, int * maxdh) {
		int h;
		if (GL->tag == 0)*maxdh = 0;
		else {
			if (GL->tag == 1 && GL->slink == NULL) {
				*maxdh = 1;
			}
			else {
				GL = GL->slink;
				*maxdh = 0;
				do {
					depth(GL, &h);
					if (h > *maxdh) {
						maxdh = h;
					}
				} while (GL != NULL);
				(*maxdh)++;
			}
		}
	}
};

int main()
{
	GLIST<char>* gl = new GLIST<char>();
	//自己定义操作。
	return 0;
}

以上即为利用C/C++泛型编程实现数据结构之广义表。类模板可复用。

猜你喜欢

转载自blog.csdn.net/qq_27180763/article/details/82751971