typedef struct BiTNode{
int data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//前序创建二叉树
void createBiTree(BiTree *T){
int value;
cin>>value;
if (value == 0)
*T = NULL;
else{
*T = (BiTree)malloc(sizeof(BiTNode));
if(!*T)
exit(OVERFLOW);
(*T)->data = value;
createBiTree(&(*T)->lchild);
createBiTree(&(*T)->rchild);
}
}
1 2 4 0 0 5 0 0 3 6 0 0 7 0 0 构建二叉树
//前序遍历
void PreOrderTraverse(BiTree T){
if(T==NULL)
return;
cout<<T->data<<" ";
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
//中序遍历
void InOrderTraverse(BiTree T){
if(T==NULL)
return;
InOrderTraverse(T->lchild);
cout<<T->data<<" ";
InOrderTraverse(T->rchild);
}
//后序遍历
void PostOrderTraverse(BiTree T){
if(T==NULL)
return;
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
cout<<T->data<<" ";
}
//测试
int main(){
BiTree T;
createBiTree(&T);
PreOrderTraverse(T); // 1 2 4 5 3 6 7
cout<<endl;
InOrderTraverse(T); // 4 2 5 1 6 3 7
cout<<endl;
PostOrderTraverse(T); // 4 5 2 6 7 3 1
return 0;
}
举例演示:
//获取Morris序列
void morris(BiTree T){
if(T==NULL)
return;
BiTree cur = T; // 初始化cur=T头节点
BiTree mostRight = NULL; // 初始化mostRight=NULL
while(cur != NULL){
mostRight = cur->lchild; //mostRight=cur的左孩子
cout<<cur->data<<" "; // 打印Morris序列
if(mostRight!=NULL){
while(mostRight->rchild!=NULL && mostRight->rchild!=cur){
mostRight = mostRight->rchild; // 将mostRight移动到cur左孩子的最右节点处
}
if(mostRight->rchild == NULL){ // mostRight的右节点为NULL
mostRight->rchild = cur; // 指向cur
cur = cur->lchild; // cur左移 下接continue直接下一次循环
continue;
} else {
mostRight->rchild = NULL; // 否则mostRight置NULL
}
}
cur = cur->rchild; // 在没有左子树或执行mostRight->rchild=NULL后执行
}
}
Morris序的特点:
1. 节点无左子树,则在Morris序中只出现一次,
2. 节点有左子树,则在Morris序中出现两次。
下面,根据得到的Morris序做先序、中序、后序遍历:
1. 先序遍历:在Morris序中第一次出现时进行打印,第二次不打印,
2. 中序遍历:在Morris序中出现一次的立刻打印,出现二次的在第二次时打印,
3. 后序遍历:在Morris序中出现两次的节点且出现在第二次时进行处理:逆序打印该节点的左子树的右边界,最后逆序单独打印二叉树的右边界。
//Morris先序遍历:
void morrisPre(BiTree T){
if(T==NULL)
return;
BiTree cur = T;
BiTree mostRight = NULL;
while(cur != NULL){
mostRight = cur->lchild;
if(mostRight!=NULL){ // 左子树不为NULL,必然Morris序列中存在两次节点
while(mostRight->rchild!=NULL && mostRight->rchild!=cur){
mostRight = mostRight->rchild;
}
if(mostRight->rchild == NULL){ // Morris序列中两次节点第一次出现的情况进行data打印
cout<<cur->data<<" ";
mostRight->rchild = cur;
cur = cur->lchild;
continue;
} else {
mostRight->rchild = NULL;
}
} else{ // Morris序列中只能有一次的情况进行data打印
cout<<cur->data<<" ";
}
cur = cur->rchild;
}
}
//Morris中序遍历:
void morrisIn(BiTree T){
if(T==NULL)
return;
BiTree cur = T;
BiTree mostRight = NULL;
while(cur != NULL){
mostRight = cur->lchild;
if(mostRight!=NULL){ // 左子树不为NULL,必然Morris序列中存在两次节点
while(mostRight->rchild!=NULL && mostRight->rchild!=cur){
mostRight = mostRight->rchild;
}
if(mostRight->rchild == NULL){ // Morris序列中两次节点第一次出现
mostRight->rchild = cur;
cur = cur->lchild;
continue;
} else { // 第二次
mostRight->rchild = NULL;
}
}
cout<<cur->data<<" "; // 打印中序序列节点
cur = cur->rchild;
}
}
//Morris后序遍历:
为保证空间复杂度为O(1),在逆序打印右边界的时候,必须对边界节点右指针的指向进行调整。
// 从now开始,只考虑右指针,将其作为单链表的next,将这个单链表逆序,返回最后一个节点
BiTree reverseEdge(BiTree T){
BiTree pre = NULL;
BiTree next = NULL;
while(T!=NULL){
next = T->rchild;
T->rchild = pre;
pre = T;
T = next;
}
return pre;
}
// 以T节点为首的树,逆序打印树的右边界
void printEdge(BiTree T){
BiTree tail = reverseEdge(T);
BiTree cur = tail;
while(cur!=NULL){
cout<<cur->data<<" ";
cur = cur->rchild;
}
reverseEdge(tail);
}
//后序序列
void morrisPost(BiTree T){
if(T==NULL)
return;
BiTree cur = T;
BiTree mostRight = NULL;
while(cur != NULL){
mostRight = cur->lchild;
if(mostRight!=NULL){ // 左子树不为NULL,必然Morris序列中存在两次节点
while(mostRight->rchild!=NULL && mostRight->rchild!=cur){
mostRight = mostRight->rchild;
}
if(mostRight->rchild == NULL){ // Morris序列中两次节点第一次出现
mostRight->rchild = cur;
cur = cur->lchild;
continue;
} else { // 出现两次且第二次出现时
mostRight->rchild = NULL;
printEdge(cur->lchild); // 进行处理
}
}
cur = cur->rchild;
}
// 结束后,逆序打印该二叉树的右边界
printEdge(T);
}
时间复杂度:O(n)
空间复杂度:O(1)
——————END-2022-06-26——————