C/C++泛型编程实现数据结构之广义表
广义表是线性表的推广,又称列表。线性表的元素只限于原子项,即每个数据元素只能是一个数或一个记录,如果放松对线性表元素的这种限制,允许他们自身具有结构,那么就产生了广义表。
广义表是一种多层次的线性结构,像是一颗倒扣的树,实际上,这也算是一种树形结构。广义表不仅是线性表的推广,也算是树结构的推广。
广义表的存储结构
广义表的元素本身可以具有结构,这是一种带有层次性的线性结构。这里我们定义了三个域。一个为tag标志位,指示了当前元素是原子还是子表。广义表规定了当tag为0时,当前原子项为原子(data),当tag为1时,当前原子项指向下一个原子子表的地址。(slink),即当广义表中的某个节点出现了data时,不可能出现节点slink。这个我们可以通过union联合体来实现。
另一个节点是link。link指向了同一层次的下一个元素的地址。类似于链表中得到next,link把每一个节点都窜通在了一起,不同于slink的是,link指向下一个节点,slink指向子表,当slink存在是,link一定为NULL。

广义表的基本操作
- 建立广义表
- 输出广义表
- 查找广义表中元素
- 获取广义表中的tail尾表
- 获取广义表深度
广义表理论存储形式直观表述

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










