数据结构之广义表
广义表定义
广义表从结构上来说是对链表的一种扩展,也就是说其中的某个节点可能又指向了另外一个链表(这样的节点叫做子表节点),那么对于广义表这种数据类型的设定一定会大量的涉及递归的算法,因为不管是广义表还是二叉树类型,它们从结构上都具有不断递归的过程。
如下图所示是广义表的常见结构:
从应用的角度来看,广义表被广泛的应用于人工智能等领域的表处理语言LISP中,在LISP语言中,广义表化i一种最基本的数据结构。下面让我么不展示LISP的程序:
//LISP语言
(defun search-start (open closed)
(let ((q (first open))
(seq (rest open)))
(cond ((null open) nil)
((find q finish-status :test 'equal) (list seq (cons q closed)))
(t (search-start (funcall
update-open-lst
seq
(expand-vertex q rules-set expand-func (cons q closed))
)
(cons q closed))))))
可以看到lisp的代码里充斥着“()”,这些就是广义表中的子表元素,针对一个广义表,我们需要了解其组织结构、元素数量、广义表深度等信息。下节我们将会设计一个广义表,如果有兴趣的同学可以学习下LISP的使用,据说掌握LISP的程序员都是天才。
广义表实现
为了简化问题的规模,我们对于广义表内数据类型设定为以下几种:整型(INT)、字符型(CHARACTER)、头结点(HEAD)和子表类型(LIST)。在枚举类型中对它们进行了定义:
//广义表节点类型
typedef enum {
HEAD = 0, //子表类型(头结点)
INT, //整型类型
CHARACTER, //子符类型
LIST //子表地址
}Node_type;
广义表中的节点内容需要有以下几个:
1.节点类型
2.实际存储的值(不同的类型值不同,可以采用共用体)
3.指向下一个广义表节点的指针
//广义表的节点结构
typedef struct Gen_node{
//1.标志(类型) int char list head
Node_type n_type;
//2.实际存储的值 int char (Gen_node *)
union {
int int_value;
char char_value;
int head_flag;
struct Gen_node *head;
} value; //根据节点类型选取不同的值
//3.next指针
struct Gen_node *next; //指向广义表的下一个元素
}Gen_node;
typedef struct Gen_node *Gen_list;
下面我们就广义表的常见接口进行介绍:
//广义表接口
Gen_list init_genlist(char *input_str) ; //广义表的创建
void destroy_genlist(Gen_list *gen_list) ; //广义表的销毁
int get_genlist_count(Gen_list gen_list); //得到广义表的元素个数
int get_genlist_depth(Gen_list gen_list); //得到广义表的深度
Gen_list copy_genlist(Gen_list gen_list) ; //广义表的拷贝
void show_genlist(Gen_list gen_list) ; //显示广义表信息
上述介绍了广义表的基本操作,下面我们来实现广义表的接口:
//gen_list.c
#include "gen_list.h"
#include "tools.h"
#include <ctype.h>
#include <strings.h>
#include <stdio.h>
static Boolean is_input_empty(const char *string);
static Boolean is_braket_match1(const char *string); //括号匹配
static Boolean is_braket_match(const char *string); //括号匹配
static Gen_list create_genlist(char *string);
//创建广义表节点
static Gen_node *create_node(void);
static Gen_node *create_head_node(int head_flag);
static Gen_node *create_int_node(int int_value);
static Gen_node *create_char_node(char character);
static Gen_node *create_list_node(Gen_n