下面这个程序是我看weiss的《数据结构与算法分析》的第四章的树里面的一个算法写的程序,具体可以看该书的第一版的71页这个给出我的实现,希望来者给出更加好的设计思路。
程序里面给出了8种遍历方式,欧拉遍历(其实就是中序加了两个括号而已),前序非递归,中序非递归,后序非递归,前序递归,中序递归,后序递归,
另外程序也添加了按层遍历二叉树,程序如下:
- #include <ctype.h>
- #include <malloc.h>
- #include <stdio.h>
- #include <queue>
- using namespace std;
- typedef struct Treenode *ptrtonode;
- typedef ptrtonode Tree;
- struct Treenode {
- char x;
- Tree lefttree;
- Tree righttree;
- } Treenode;
- typedef struct List_Stack {
- struct List_Stack *next;
- Tree mytree;
- } Node, *LS;
- void initstack(LS *a) {
- (*a) = (LS)malloc(sizeof(Node));
- (*a)->next = NULL;
- }
- bool stackempty(const LS a) {
- return a->next == NULL;
- }
- /* 链栈一般不会满,不测试
- bool stackfull(const LS a) {
- return !stackempty(a);
- }
- */
- void push(LS *lstack, Tree a) {
- LS res = (LS)malloc(sizeof(Node));
- res->mytree = a;
- res->next = (*lstack)->next;
- (*lstack)->next = res;
- }
- Tree pop(LS *lstack) {
- if (stackempty(*lstack)) {
- printf("Pop error,stack is empty!/n");
- return NULL;//打印一个笑脸
- }
- LS p = (*lstack)->next;
- Tree x = p->mytree;
- LS pnext = p->next;
- //free(p);
- (*lstack)->next = pnext;
- return x;
- }
- bool isoperator(char a) {
- if(a == '-' || a == '+' || a == '*' || a == '/')
- return 1;
- else
- return 0;
- }
- Tree chartotree(char a) {
- Tree mytree = (Tree)malloc(sizeof(Treenode));
- mytree->x = a;
- mytree->lefttree = mytree->righttree = NULL;
- return mytree;
- }
- bool exnode(Tree x) { //外节点,也就是叶子节点
- if( (x->righttree == NULL) && (x->lefttree == NULL) ) {
- return 1;
- }
- else
- return 0;
- }
- bool innode(Tree x) { //内节点,也就是中间节点
- return !exnode(x);
- }
- //欧拉遍历方式,跟中序遍历类似
- void eulervisit(Tree x) {
- if(exnode(x) ) {
- printf("%c", x->x);
- }
- else {
- printf("(");
- eulervisit(x->lefttree);
- printf("%c", x->x);
- eulervisit(x->righttree);
- printf(")");
- }
- }
- //中序递归的遍历方式
- bool midvisit(Tree x) {
- if(x) {
- if(midvisit(x->lefttree))
- if(printf(" %c ", x->x))
- if(midvisit(x->righttree))
- return 1;
- return 0;
- }
- else
- return 1;
- }
- //前序递归的遍历方式
- bool previsit(Tree x) {
- if(x) {
- if(printf(" %c ", x->x))
- if(previsit(x->lefttree))
- if(previsit(x->righttree))
- return 1;
- return 0;
- }
- else
- return 1;
- }
- //后序递归的遍历方式
- void postvisit(Tree x) {
- if(x) {
- postvisit(x->lefttree);
- postvisit(x->righttree);
- printf(" %c ", x->x);
- }
- }
- //前序的非递归遍历
- void preordervisit(Tree x) {
- LS a;
- initstack(&a);
- Tree p = x;
- while (p || !stackempty(a))
- {
- if (p)
- {
- push(&a, p);
- printf(" %c ", p->x);
- p = p->lefttree;
- }
- else {
- p = pop(&a);
- p = p->righttree;
- }
- }
- }
- //中序的非递归遍历
- void inordervisit(Tree x) {
- LS a;
- initstack(&a);
- Tree p = x;
- while (p || !stackempty(a))
- {
- if (p)
- {
- push(&a, p);
- p = p->lefttree;
- }
- else {
- p = pop(&a);
- printf(" %c ", p->x);
- p = p->righttree;
- }
- }
- }
- /***********************************************************************
- /*后序的非递归遍历,后序遍历有点复杂,
- /*要给出一个标记表明左边和右边子树都已经遍历,
- /*这里就不使用开始时候的堆栈了,
- /*用数组堆栈实现效果更加好,惟一的缺点就是堆栈有最大限制 */
- /************************************************************************/
- void postordervisit(Tree x) {
- Tree stack[100], p;
- int tag[100], top;
- top = 0;
- p = x;
- do
- {
- while (p != NULL) //扫描左子树,入栈
- {
- top++;
- stack[top] = p;
- tag[top] = 0; //右边子树还没有访问设置为0
- p = p->lefttree;
- }
- if (top > 0)
- {
- if (tag[top] == 1)
- {
- printf(" %c ", stack[top]->x);
- top--;
- }
- else {
- p = stack[top];
- if (top > 0)
- {
- p = p->righttree;
- tag[top] = 1;
- }
- }
- }
- } while ((p != NULL) || (top != 0));
- }
- Tree createtree(char *a) { //根据数据结构与算法分析的71页的算法设计一个表达式树
- LS x;
- initstack(&x);
- char *p = a;
- while( *p != '/0') {
- Tree a, b;
- Tree mytree;
- if( isalpha(*p) ) {
- mytree = chartotree(*p);
- push(&x, mytree);
- }
- if( isoperator(*p) ) {
- mytree = chartotree(*p);
- a = pop(&x);
- b = pop(&x);
- mytree->righttree = a;
- mytree->lefttree = b;
- push(&x, mytree);
- }
- p++;
- }
- Tree root = pop(&x);
- return root;
- }
- void deletenode(Tree *p) { //按层遍历
- queue<Tree> que;
- que.push(*p);
- Tree temp;
- while(!que.empty()) {
- temp = que.front();
- que.pop();
- if(temp->lefttree)
- que.push(temp->lefttree);
- if(temp->righttree)
- que.push(temp->righttree);
- //free(temp);
- printf("%c", temp->x);
- temp = NULL;
- }
- }
- int main(int argc, char* argv[])
- {
- LS x;
- initstack(&x);
- if (stackempty(x))
- printf("stack is empty!/n");
- else
- printf("stack is full!/n");
- printf("%c/n", pop(&x));
- char *p = "abc*+b-";
- Tree root = createtree(p);
- //等待进一步的实现来实现二叉树的遍历
- //用到exnode和innode函数
- eulervisit(root);
- puts("/n中序递归");
- midvisit(root);
- puts("/n中序非递归");
- inordervisit(root);
- puts("/n前序递归");
- previsit(root);
- puts("/n前序非递归");
- preordervisit(root);
- puts("/n后序递归");
- postvisit(root);
- puts("/n后序非递归");
- postordervisit(root);
- deletenode(&root);
- return 0;
- }