二叉树的部分操作
来源:互联网 发布:路由器域名重定向设置 编辑:程序博客网 时间:2024/04/30 04:29
以下代码包括二叉树的创建、前中后序遍历(递归)、非递归中序遍历(栈实现)、层序遍历(队列实现)和中序线索化遍历。
- main
#include<stdio.h>#include<stdlib.h>#include<iostream>#include"Tree.h"#include"Queue.h"#include"Stack.h"#include"Tree.h"#include"Marco.h"using namespace std;BiThrTree pre;//全局变量,表示刚刚访问过的结点int main(){ BiThrTree T = NULL; printf("二叉树测试程序开始:\n"); printf("1.创建非空二叉树:\n"); CreateBiThrTree(T); printf("\n2.前序遍历二叉树:\n"); PreOrderTraverse(T); printf("\n3.中序遍历二叉树:\n"); InOrderTraverse(T); printf("\n4.后序遍历二叉树:\n"); PostOrderTraverse(T); printf("\n5.非递归中序遍历二叉树(用栈实现):\n"); NoRecursionInTraverse(T); printf("\n6.层序遍历二叉树(用队列实现):\n"); LevelOrderTraverse(T); printf("\n7.中序线索化遍历二叉树:\n"); BiThrTree Thrt; InOrderThreading( Thrt,T ); InOrderAfterThreading(Thrt); cout << "\n二叉树测试程序结束!" << endl; return OK;}
2.Tree.c
#include<stdio.h>#include<stdlib.h>#include<iostream>#include"Tree.h"#include"Stack.h"#include"Queue.h"#include"Marco.h"using namespace std;extern BiThrTree pre;/********************对二叉树的操作********************///1.创建二叉树int CreateBiThrTree(BiThrTree &T){ char data; scanf("%c", &data); if (' ' == data) { T = NULL; //如果字符为空,则根节点为空 } else { if (!(T = (BiThrTree)malloc(sizeof(BiThrNode))))//否则建立根节点 { printf("出错:创建结点时分配空间错误!"); exit(OVERFLOW); } T->data = data; //根节点数据域 T->LTag = Link; T->RTag = Link; CreateBiThrTree(T->lchild); //构造左子树 CreateBiThrTree(T->rchild); //构造右子树 } return OK;}//2.前序遍历void PreOrderTraverse(BiThrTree T){ if (T) { printf("%c", T->data); PreOrderTraverse(T->lchild); PreOrderTraverse(T->rchild); }}//3.中序遍历void InOrderTraverse(BiThrTree T){ if (T) { InOrderTraverse(T->lchild); printf("%c", T->data); InOrderTraverse(T->rchild); }}//4.后序遍历void PostOrderTraverse(BiThrTree T){ if (T) { PostOrderTraverse(T->lchild); PostOrderTraverse(T->rchild); printf("%c", T->data); }}//5.非递归中序遍历void NoRecursionInTraverse(BiThrTree T){ BiThrTree p; Stack s; if (!(s.base = (BiThrTree*)malloc(sizeof(BiThrNode)))) //初始化栈 { printf("出错:栈初始化失败时分配存储空间失败!\n"); exit(1); } s.top = s.base; s.stackSize = STACK_INIT_SIZE; p = T; while(p || (s.top - s.base)) { while (p) //遍历左子树,直到最左下角的节点 { Push(s, p); p = p->lchild; } if((s.top-s.base)) //左子树为空,根结点退栈,再遍历右子树 { Pop(s, p); printf("%c", p->data); p = p->rchild; } }}//6.层序遍历void LevelOrderTraverse(BiThrTree T){ Queue Q; BiThrTree p=T; //p在过程中不断被赋予新的结点地址 Q.front = Q.rear = (QPtr)malloc(sizeof(QNode)); //初始化链队列 if (!Q.front) { cout << "\n初始化分配存储空间失败!\n" << endl; exit(1); } Q.front->next = NULL; if (p) EnQueue(Q, p); while (Q.front != Q.rear) { DelQueue(Q, p); //将被删除的结点赋予p,从而实现结点的更新 cout << p->data; if (p->lchild != NULL) { EnQueue(Q, p->lchild); } if (p->rchild != NULL) { EnQueue(Q, p->rchild); } }//while}//7.中序线索化遍历int InOrderThreading(BiThrTree &Thrt,BiThrTree T){ if (!(Thrt = (BiThrTree)malloc(sizeof(BiThrNode)))) { printf("出错:分配空间错误!"); exit(-2); } Thrt->LTag = Link; //建立头节点 Thrt->RTag = Thread; Thrt->rchild = Thrt; //右指针回指指向头节点 if (!T) //二叉树空,头节点的lchild指向根节点 { Thrt->lchild = Thrt; } else { Thrt->lchild = T; //T不为空,头节点的lchild连接根结点 pre = Thrt; //全局变量pre初始化,始终指向刚刚访问过的结点 InThreading(T); //中序遍历进行中序线索化,传入的是根结点 pre->rchild = Thrt; pre->RTag = Thread; Thrt->rchild = pre; //最后一个结点进行线索化 } return OK;}void InThreading(BiThrTree p){ if (p) { InThreading(p->lchild); //递归,左子树线索化,直至最左下角的结点,其左子树为空,不在继续递归 //中间部分为对 当前结点 的线索化 if (!p->lchild) //当前结点 没有左子树,前驱线索 { p->LTag = Thread; p->lchild = pre; //p->lchild指向直接前驱 } if (!pre->rchild) //刚访问过的结点 没有右子树,后继线索 { pre->RTag = Thread; pre->rchild = p; // } pre = p; //保持pre指向刚刚访问过的结点 InThreading(p->rchild); //递归,右子树线索化 }}//利用已经线索化的二叉树进行中序遍历输出, 非递归void InOrderAfterThreading(BiThrTree Thrt) //传入的是pre,传入前进行的最后操作为: { //pre->rchild = Thrt;pre->RTag = Thread;Thrt->rchild = pre; BiThrTree p; p = Thrt->lchild; while (p != Thrt) { while (p->LTag == Link) { p = p->lchild; } cout << p->data; while (p->RTag == Thread && p->rchild != Thrt) { p = p->rchild; cout << p->data; } p = p->rchild; }}
3.Stack.c
#include<stdio.h>#include<stdlib.h>#include"Stack.h"#include"Tree.h"/***********************对栈的操作***********************///1.Pushvoid Push(Stack &s, BiThrTree e){ // 栈满,追加空间 if (s.top - s.base >= s.stackSize) { s.base = (BiThrTree *)realloc(s.base, (s.stackSize + STACKINCREMENT) * sizeof(BiThrNode)); if (!s.base) exit(0); s.top = s.base + s.stackSize; s.stackSize = s.stackSize + STACKINCREMENT; } *(s.top) = e; // 存放数据 s.top++;}//2.Popvoid Pop(Stack &s, BiThrTree &e){ if (s.top == s.base) { printf("\n出错:出栈时栈为空!\n"); exit(-2); } e = *(--s.top); // 将栈顶元素弹出并修改栈指针}
4.Queue.c
#include<stdio.h>#include<stdlib.h>#include<iostream>#include"Queue.h"#include"Marco.h"#include"Tree.h"using namespace std;/*******************对队列的操作***************************///1.EnQueuevoid EnQueue(Queue &Q, BiThrTree e){ QPtr q; if (!(q = (QPtr)malloc(sizeof(QNode)))) { printf("出错:队列分配存储空间失败!\n"); exit(OVERFLOW); } q->data = e; q->next = NULL; Q.rear->next = q; Q.rear = q;}//2.DelQueuevoid DelQueue(Queue &Q, BiThrTree &e){ if (Q.front == Q.rear) { cout << "出错:执行删除操作的队列为空!" << endl; exit(1); } QPtr p = Q.front->next; e = p->data; Q.front->next = p->next; if (Q.rear == p) { Q.rear = Q.front; } free(p);}
5.Tree.h
#ifndef TREE_H_#define TREE_H_#include<stdio.h>#define STACK_INIT_SIZE 100#define STACKINCREMENT 10typedef enum PointerTag { Link, Thread }; //Link==0,表示指针,Thread==1,表示线索typedef struct BiThrNode{ char data; struct BiThrNode *lchild; struct BiThrNode *rchild; PointerTag LTag; PointerTag RTag;}BiThrNode, *BiThrTree;/********************对二叉树的操作********************///1.创建int CreateBiThrTree(BiThrTree &T);//2.前序遍历void PreOrderTraverse(BiThrTree T);//3.中序遍历void InOrderTraverse(BiThrTree T);//4.后序遍历void PostOrderTraverse(BiThrTree T);//5.非递归中序遍历void NoRecursionInTraverse(BiThrTree T);//6.层序遍历void LevelOrderTraverse(BiThrTree T);//7.中序遍历并线索int InOrderThreading(BiThrTree &Thrt,BiThrTree T);void InThreading(BiThrTree p);//利用已经线索化的二叉树进行中序遍历输出void InOrderAfterThreading(BiThrTree Thrt);#endif
6.Stack.h
#ifndef STACK_H_#define STACK_H_#include"Tree.h"typedef struct{ BiThrTree *top; BiThrTree *base; int stackSize;}Stack; //用于非递归遍历二叉树/*******************需要的对栈的操作***********************///1.Pushvoid Push(Stack &s, BiThrTree e);//2.Popvoid Pop(Stack &s, BiThrTree &e);#endif
7.Queue.h
#ifndef QUEUE_H_#define QUEUE_H_#include"Tree.h"typedef struct QNode //用于层序遍历二叉树{ BiThrTree data; //存储地址 struct QNode *next;}QNode, *QPtr;typedef struct{ QPtr front; QPtr rear;}Queue;/******************对队列的操作****************************///1.EnQueuevoid EnQueue(Queue &Q, BiThrTree e);//2.DelQueuevoid DelQueue(Queue &Q, BiThrTree &e);#endif
8.Marco.h(此部分的代码作用暂时不大)
#ifndef MARCO_H_#define MARCO_H_#define OK 0#define ERROR 1//#define OVERFLOW -2#endif
在编写二叉树的线索化的代码时,一直不清楚线索化的具体过程,尽管看上去很容易理解。希望在调试的过程中理解过程,但很难进行下去,因为并没有能够运行的代码,每当想到这里就果断放弃调试,感觉是对时间的浪费。终于,今天静下心来,搜到了一个二叉树动态线索化的网页,观看后勉强理解了,代码写出后,进行调试,进一步理解过程。当然,写代码时不断抄袭书中内容的习惯一直是硬伤,鉴于二叉树的重要性,打算完全靠自己重新写一次。望天道酬勤!
ps:在写这个程序期间,学习了部分C++的知识,但在上述代码中所夹杂的C++代码都是基本的输出,没有输入。(如有错误,望各位指出)。
1 0
- 二叉树的部分操作
- 二叉树的部分操作实现
- 有关二叉树的部分操作
- 二叉树的基本操作及部分面试题
- 二叉树的基本操作及部分面试题
- 二叉查找树的各项操作(重点是结点的删除部分和递归的运用)
- 数据结构面试之五—二叉树的常见操作(递归实现部分)
- 数据结构面试之五—二叉树的常见操作(递归实现部分
- 数据结构面试之五—二叉树的常见操作(递归实现部分)
- 二叉树的操作
- 二叉树的操作
- 二叉树的操作
- 二叉树的操作
- 二叉树的操作
- 二叉树的操作
- 二叉树的操作
- 二叉树的操作
- 二叉树的操作
- PHP文件处理--打开文件
- 解决listview与scrollview结合使用时出现的问题
- requirejs加载css
- 第六周项目1==分数类的雏形
- 基于halcon工业图像处理——初学
- 二叉树的部分操作
- hdu1432
- 文章标题
- Implementing a Neural Network from Scratch in Python – An Introduction
- ceshi
- 数据分析入门(谁说菜鸟不会数据分析)
- Android webview使用详解
- poj 3669 meteor shower
- 数据库sql