1.二叉链表求树的层次遍历
层次遍历需要用到队列,为加深理解,这里手敲队列
#include <stdio.h>
#include<malloc.h>
#define MAX 100
typedef int Element;
typedef struct tree
{
Element ch;
struct tree *left;
struct tree *right;
}Tree;
typedef struct queue
{
Tree *a[MAX];
int front;
int rear;
}Queue;
Queue Qu;
void Init();
int InsertQueue(Element ch);
Tree *DeleteQueue();
void CreateTree(Tree **r);
void TransLevele(Tree *r);
void PrintTree(Tree *r);
int main()
{
Tree *r=NULL;
CreateTree(&r);
PrintTree(r);
printf("\n");
TransLevele(r);
while(1)getchar();
return 0;
}
void Init()
{
int i=0;
for (i=0; i<MAX; i++)
{
Qu.a[i] = NULL;
}
Qu.front = 0;
Qu.rear = 0;
}
int InsertQueue(Tree *r)
{
if ( (Qu.rear+1)%MAX == Qu.front)
{
printf("Queue full!");
return 0;
}
Qu.a[Qu.rear] = r;
Qu.rear = (Qu.rear+1)%MAX;
return 1;
}
Tree *DeleteQueue()
{
if (Qu.front == Qu.rear)
{
printf("\nQueue empty");
return NULL;
}
Tree *t=NULL;
t = Qu.a[Qu.front];
Qu.front = (Qu.front+1)%MAX;
return t;
}
void CreateTree(Tree **r)
{
Element ch;
ch=getchar();
if (ch=='#')
{
(*r)=NULL;
return ;
}
*r = (Tree *)malloc(sizeof(Tree));
(*r)->ch = ch;
CreateTree(&((*r)->left));
CreateTree(&((*r)->right));
}
void PrintTree(Tree *r)
{
if (r==NULL)
{
return ;
}
printf("%c",r->ch);
PrintTree(r->left);
PrintTree(r->right);
}
void TransLevele(Tree *r)
{
if (r==NULL)
{
return ;
}
printf("%c",r->ch);
if (r->left != NULL)
{
InsertQueue(r->left);
}
if (r->right != NULL)
{
InsertQueue(r->right);
}
Tree *t = DeleteQueue();
TransLevele(t);
}
2.带双亲域遍历,只能支持前后序遍历(原因很简单,因为该结构中不存在左右儿子结点)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<string>
#include<stack>
#include<queue>
#include<algorithm>
#include<iostream>
#define TElemType char
#define Max 100
using namespace std;
typedef struct TNode
{
TElemType data;
int parent;
}TNode;
typedef struct Tree
{
TNode parent[Max];
int NodeNum;
}Tree;
void InitTree(Tree &T)
{
for (int i=0;i<Max;i++)
{
T.parent[i].data = '#';
T.parent[i].parent = -1;
}
T.NodeNum = 0;
}
//插入树的结点 参数:树T,结点node 作用:在双亲数组中插入结点,增加树的结点值
bool InsertNode(Tree &T, TElemType node)
{
if (node != '#')
{
T.parent[T.NodeNum++].data = node;//插入到双亲数组中
return true;
}
return false;
}
//插入双亲数组的双亲域 参数:树T ,结点node1,结点node2
//作用:使双亲数组中,node2对应的双亲域为node1的下标
bool InsertParent(Tree &T, TElemType node1, TElemType node2)
{
int place1, place2;
place1 = -1;place2 = -1;
for (int i=0;i<T.NodeNum;i++)//查找两点是否存在
{
if (node1 == T.parent[i].data)place1 = i;
if (node2 == T.parent[i].data)place2 = i;
}
if (place1 != -1 && place2 != -1)//两点均存在
{
T.parent[place2].parent = place1;
return true;
}
return false;
}
void PreOrder(Tree T,int i)
{
if (T.NodeNum != 0)
{
cout << T.parent[i].data << " ";
for(int j=0;j<T.NodeNum;j++)
{
if(T.parent[j].parent==i)
PreOrder(T,j);
}
}
}
void CreateTree(Tree &T)
{
int nodenum = 0;
int parent;
TElemType node,node1,node2;
printf("请输入树的结点个数:");
cin >> nodenum;
parent = nodenum - 1;
printf("请输入树的结点名称(空格隔开):");
while (nodenum--)
{
cin >> node;
InsertNode(T,node);
}
printf("请输入树的结点间的双亲关系(一对为一双亲关系,A B表示A为B的双亲):\n");
while (parent--)
{
cin >> node1>>node2;
InsertParent(T,node1,node2);
}
printf("\n");
}
int main()
{
Tree T;
InitTree(T);
CreateTree(T);
PreOrder(T,0);
while(1)getchar();
return 0;
}
3.树的递归遍历(最简短)
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define TRUE 1
#define FALSE 0
#define SIZEINIT 10
#define INCRESIZE 5
typedef int Status;
typedef char TElemType;
typedef struct node{
TElemType data;
struct node *lchild,*rchild;
}BiTNode,*BiTree;
//前序创建二叉树
void CreateBiTree(BiTree &T){
char ch;
scanf("%c",&ch);
if(ch=='#'){
T = NULL;
}else{
T = (BiTree)malloc(sizeof(struct node));
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
//前序遍历
Status PreOrderTraverse(BiTree T,Status (*Visit)(TElemType e)){
if(T){
if(Visit(T->data)){
if(PreOrderTraverse(T->lchild,Visit)){
if(PreOrderTraverse(T->rchild,Visit)) return OK;
}
}
return ERROR;
}
return OK;
}
//中序遍历
Status InOrderTraverse(BiTree T,Status (*Visit)(TElemType e)){
if(T){
if(InOrderTraverse(T->lchild,Visit)){
if(Visit(T->data)){
if(InOrderTraverse(T->rchild,Visit)) return OK;
}
}
return ERROR;
}
return OK;
}
//后序遍历
Status PostOrderTraverse(BiTree T,Status (*Visit)(TElemType e)){
if(T){
if(PostOrderTraverse(T->lchild,Visit)){
if(PostOrderTraverse(T->rchild,Visit)){
if(Visit(T->data)) return OK;
}
}
return ERROR;
}
return OK;
}
//访问函数
Status Visit(TElemType e){
printf("%c",e);
return OK;
}
int main(){
BiTree T = NULL;
printf("请前序创建第一棵树(空位置用'#'来代替)\n");
CreateBiTree(T);
printf("\n二叉树前序遍历的结果\n");
PreOrderTraverse(T,Visit);
printf("\n二叉树中序遍历的结果\n");
InOrderTraverse(T,Visit);
printf("\n二叉树后序遍历的结果\n");
PostOrderTraverse(T,Visit);
printf("\n");
while(1)getchar();
return 0;
}
//AB#D##CE###
4.先序建立二叉链表求后序遍历序列
思路:初始结点标记为零 对于某个结点先遍历完其左子树(不断压左子树结点进栈),然后结点标记++,表示其左子树全部遍历,之后如果无右子树直接出栈输出,否则遍历其右子树同时将其标记++,对于标记为2的结点马上输出并出栈
#include <iostream>
#include<stack>
#include<malloc.h>
using namespace std;
typedef struct node {
char data;
struct node* left = NULL;
struct node* right = NULL;
int times = 0;
}node,*tree;
inline void initial(tree &T)
{
char ch;
cin>>ch;
if(ch=='#')
{
T=NULL;
return ;
}
else
{
T=(tree)malloc(sizeof(node));
T->data=ch;
initial(T->left);
initial(T->right);
}
}
inline void display(tree &T)
{
if(!T)return ;
cout<<T->data<<endl;
display(T->left);
display(T->right);
}
int main()
{
tree T=(tree)malloc(sizeof(node));
initial(T);
cout<<"begin"<<endl;
display(T);
cout<<"begin"<<endl;
stack<tree> s;
tree p=T;
while (p != nullptr || !s.empty()) {
if (p == nullptr) {
p = s.top();
s.pop();
p->times++;
}
else {
if (p->times == 2) {
cout << p->data << " ";
p = nullptr;
}
else if(p->times==1) {
s.push(p);
p = p->right;
}
else {
s.push(p);
p = p->left;
}
}
}
return 0;
}
5.线索二叉树中序遍历
主要思想是将其空节点改造为前驱指针和后继指针
#include <stdlib.h>
#include <stdio.h>
#define elemtype char
#define Status int
const int ERROR = 0;
const int OK = 1;
typedef enum pointer{
tlink,thread
}fingurePointer;
typedef struct binNode{
struct binNode *lchild,*rchild;
fingurePointer ltag,rtag;
elemtype data;
}thrNode,*orderTree;
orderTree pre;
/*前序遍历的递归创建树*/
void CreateBiTree(orderTree *T)
{
char ch;
scanf("%c",&ch);
if(ch=='#')
*T=NULL;
else
{
*T=(struct binNode *)malloc(sizeof(thrNode));
if(!*T)
exit(-1);
(*T)->data=ch;
(*T)->ltag = tlink;
(*T)->rtag = tlink;
CreateBiTree(&(*T)->lchild);
CreateBiTree(&(*T)->rchild);
}
}
void visit(orderTree node)
{
orderTree p;
p = node;
if(p!=NULL)
{
visit(p->lchild);
printf("%d %c %d\n",p->ltag,p->data,p->rtag);
visit(p->rchild);
}
}
//中序线索二叉树
void inThreading(orderTree node)
{
if(node)
{
inThreading(node->lchild);//线索化左子树
if(!node->lchild){//左子树为空,改变ltag,指定lchild为pre
node->ltag = thread;
node->lchild = pre;
}
if(!pre->rchild)//右子树为空,改变rtag,指定pre的 rchild
{
pre->rtag = thread;
pre->rchild = node;
}
pre= node;
inThreading(node->rchild);
}
}
Status InOrderThreading(orderTree &head,orderTree root)
{
if(!(head=(struct binNode *)malloc(sizeof(struct binNode))))
return ERROR;
/*头结点左孩子指向根节点,右节点指向直接前驱*/
head->ltag = tlink; head->rtag = thread;
head->rchild = head;//右指针回指
if(!root) head->lchild = head;
else{
head->lchild = root;
pre = head;
inThreading(root);
pre->rchild = head;
pre->rtag = thread;
head->rchild = pre;
}
return OK;
}
void visitNode(orderTree p)
{
if(p!=NULL)
printf("%c ",p->data);
}
Status InOderTranverse(orderTree head)
{
orderTree p;
p = head->lchild;//p指向根节点
while(p!=head)
{
//左子树
while(p->ltag==tlink)
p = p->lchild;
visitNode(p);
//右子树
while(p->rtag ==thread&&p->rchild!=head)
{
p = p->rchild;
visitNode(p);
}
p = p->rchild;
}
return OK;
}
int main()
{
orderTree root;
CreateBiTree(&root);
orderTree head;
Status x = InOrderThreading(head,root);
InOderTranverse(head);
while(1)getchar();
}