本程序改编自课本例题,包括广义链表的建立,输出,求链表长度,深度,求原子个数和最大原子(ascii)。大量应用了递归。全部代码如下:(感觉学习递归也没啥太好的方法,对问题情景理解透彻后,自然就会确定递归体了,做到对问题分析的不重不漏)
#include<iostream>
using namespace std;
#include<stdio.h>
struct Node {
int type; //1 表示子表表头 0表示原子节点
union {
char value;
Node* ptChildHead;
}valOrPt;
Node* ptNext;
};
Node* creatGenerList(char *&ptCHar) {
Node* pt;
char s = *ptCHar; //简单的标准例子如(a,b,c,d)
if (s == '(') {
pt = new Node;
pt->type = 1; //1 is child list, 0 is value
ptCHar++;
pt->valOrPt.ptChildHead = creatGenerList(ptCHar);//深度递归,建立子表
}
else if (s == '#') {
ptCHar++;//通过与后面的ptChar++结合,使字符指针越过右括号,在后面的
return NULL;//if判断里,判断的是右括号后的逗号或'\0'
}
else if (s == '\0')//当给了空字符串,表示表不存在,连空表都不算
pt = NULL;
else { //表明传递来的是字符,建立原子节点
pt = new Node;
pt->type = 0;
pt->valOrPt.value = s;
}
ptCHar++;
s = *ptCHar;
if(pt != NULL) //当这个表存在时,可以为空表,这是为了程序的健壮性
if (s == ',') {
ptCHar++;
pt->ptNext = creatGenerList(ptCHar);//广度递归,建立同层下一个元素节点
}
else if (s == ')' || s == '\0')//与'\0'比较,是为了区分(#)与((#),a)与(a,(#))
pt->ptNext = NULL;
return pt;
//通过这四个例子模拟加想象,递归过程已可以保证是正确的。
}
void displayList(Node* ptHead) {
if (ptHead == NULL) return;//对应于表不存在,连空表都不是
if (ptHead->type == 0)
cout << ptHead->valOrPt.value;
else if (ptHead->type == 1) {
cout << '(';
if (ptHead->valOrPt.ptChildHead == NULL)
cout << "#";
else
displayList(ptHead->valOrPt.ptChildHead);
cout << ')';//这个右括号加的是神来之笔,把表作为元素看待
}
if (ptHead->ptNext != NULL) {
cout << ',';
displayList(ptHead->ptNext);
}
}
int lengthList(Node* ptHead) {
if (ptHead == NULL) return 0; //表不存在
int length = 0;
ptHead = ptHead->valOrPt.ptChildHead;
while(ptHead != NULL) {
length++;
ptHead = ptHead->ptNext;
}
return length; //表不存在或者为空表,都返回0
}
int depthList(Node *ptHead) {
if (ptHead->type == 0)
return 0;
else if (ptHead->valOrPt.ptChildHead == NULL)
return 1;
else {
int max = 0;
ptHead = ptHead->valOrPt.ptChildHead;
while (ptHead != NULL) {
if (max < depthList(ptHead))
max = depthList(ptHead);
ptHead = ptHead->ptNext;
}
return max + 1;
}
}
int numberOfAtomic(Node *ptHead) {
//表不存在,或者是遇到了空表
if (ptHead == NULL || ptHead->valOrPt.ptChildHead == NULL)
return 0;
ptHead = ptHead->valOrPt.ptChildHead;
int number = 0;
while (ptHead != NULL) {
if (ptHead->type == 0)
number++;
else
number += numberOfAtomic(ptHead);
ptHead = ptHead->ptNext;
}
return number;
}
char bigggestChar(Node *ptHead) {
if (ptHead == NULL || ptHead->valOrPt.ptChildHead == NULL)
return '\0';
char s = '\0';
ptHead = ptHead->valOrPt.ptChildHead;
while (ptHead != NULL) {
if (ptHead->type == 0 && s < ptHead->valOrPt.value)
s = ptHead->valOrPt.value;
else if (ptHead->type == 1 && s < bigggestChar(ptHead))
s = bigggestChar(ptHead);
ptHead = ptHead->ptNext;
}
return s;
}
int main() {
char chars[100] = "(b,(b,a,(#),d),((a,m),c,((#))))";
char* ptChar = chars;
Node* ptHead = creatGenerList(ptChar);
cout << "the list is as follows : ";
displayList(ptHead);
cout << endl << "list length is : " << lengthList(ptHead);
cout << endl << "list depth is : " << depthList(ptHead);
cout << endl << "numbers of atomic elements is :" << numberOfAtomic(ptHead);
cout << endl << "the biggest char is : " << bigggestChar(ptHead);
return 0;
}
测试结果如下:
换多个字符串例子,测试结果都可以准确显示。谢谢阅读。看代码,建议复制到vs studio里,条理层次关系会更清晰。