C/C++泛型编程实现数据结构之广义表
  TEZNKK3IfmPf 2023年11月14日 21 0
广义表是线性表的推广,又称列表。线性表的元素只限于原子项,即每个数据元素只能是一个数或一个记录,如果放松对线性表元素的这种限制,允许他们自身具有结构,那么就产生了广义表。

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

广义表的存储结构

广义表的元素本身可以具有结构,这是一种带有层次性的线性结构。这里我们定义了三个域。一个为tag标志位,指示了当前元素是原子还是子表。广义表规定了当tag为0时,当前原子项为原子(data),当tag为1时,当前原子项指向下一个原子子表的地址。(slink),即当广义表中的某个节点出现了data时,不可能出现节点slink。这个我们可以通过union联合体来实现。

另一个节点是link。link指向了同一层次的下一个元素的地址。类似于链表中得到next,link把每一个节点都窜通在了一起,不同于slink的是,link指向下一个节点,slink指向子表,当slink存在是,link一定为NULL。

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

广义表的基本操作

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

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

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

代码实现广义表结构

其中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++泛型编程实现数据结构之广义表。类模板可复用。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月14日 0

暂无评论

推荐阅读
  TEZNKK3IfmPf   19天前   26   0   0 C++
  TEZNKK3IfmPf   19天前   22   0   0 指针C++
  TEZNKK3IfmPf   2024年05月31日   23   0   0 算法C++
  TEZNKK3IfmPf   2024年04月19日   39   0   0 泛型java
TEZNKK3IfmPf