【笔记】二叉树(递归、栈)遍历、中序线索建立和遍历

  1. 二叉树(递归)遍历
  2. 二叉树(栈)遍历
  3. 建立中序线索、遍历中序线索
    (补丁)
  4. 释放内存

《王道2022考研数据结构复习指导》P136左右


打印

2021年06月19日18:02:03
		--15
				--14
			--13
					--12
				--11
	--10
		--9
			--8
--7
		--6
	--5
			--4
		--3
				--2
			--1
------------------------------------
			--1
				--2
		--3
			--4
	--5
		--6
--7
			--8
		--9
	--10
				--11
					--12
			--13
				--14
		--15
------------------------------------
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
free(2) free(1) free(4) free(3) free(6) free(5) free(8) free(9) free(12) free(11) free(14) free(13) free(15) free(10) free(7) done!
[1] + Done                       "/usr/bin/gdb" --interpreter=mi --tty=${DbgTerm} 0<"/tmp/Microsoft-MIEngine-In-6lcpbyy3.yyk" 1>"/tmp/Microsoft-MIEngine-Out-5o1r5kf4.o1n"

Press any key to continue...

实现

#include <iostream>

using namespace std;

// ============== tree ===================

typedef struct BitNode {
    int data;
    struct BitNode *lchild, *rchild;
    int ltag=0, rtag=0;
} *BitTree;

void newBitNode(BitNode* &n, int data) {
    n = (BitNode*)malloc(sizeof(BitNode));
    n->data=data;
    n->lchild=NULL;
    n->rchild=NULL;
    n->ltag=n->rtag=0;
}

void freeTree(BitTree &T) {
    if(T==NULL) return;
    int i = T->data;
    if(T->ltag!=1) // 补丁:避免建立线索后死循环
        freeTree(T->lchild);
    if(T->rtag!=1) // 补丁:避免建立线索后死循环
        freeTree(T->rchild);
    free(T);
    T==NULL;
    cout << "free("<<i<<") ";
}

BitNode* findTreeFirstTreadNode(BitNode *p) {
    while(p->ltag==0) p=p->lchild;
    return p;
}

BitNode* findTreeNextTreadNode(BitNode *p) {
    if(p->rtag==0) return p=findTreeFirstTreadNode(p->rchild);
    return p->rchild;
}

void printTreeInThread(BitTree T) {
    BitNode *p=findTreeFirstTreadNode(T);
    while(p!=NULL) {
        cout<<p->data<<",";
        p=findTreeNextTreadNode(p);
    }
    cout<<endl;
    return;
}

void _buildTreeInThread(BitTree &p, BitNode* &pre) { // 中序线索
    if(p==NULL) return;
    _buildTreeInThread(p->lchild, pre);
    if(p->lchild==NULL) 
    {
        p->lchild=pre;
        p->ltag=1;
    }
    if(pre!=NULL&&pre->rchild==NULL)
    {
        pre->rchild=p;
        pre->rtag=1;
    }
    pre=p;
    _buildTreeInThread(p->rchild, pre);
}

void buildTreeInThread(BitTree &T) { // 中序线索
    BitNode* pre=NULL;
    if(T!=NULL) {
        _buildTreeInThread(T, pre);
        pre->rchild=NULL;
        pre->rtag=1;
    }
}

void viewNode(BitNode *n, int offset) { // -90°
    for(int i=0; i<offset; i++) cout << "\t";
    cout<<"--"<<n->data<<endl;
}

void _printNode(BitNode *n, int offset) { // 递归遍历
    if(n==NULL) return;
    int new_offset = offset+1;
    if(n->rtag!=1) // 补丁:避免建立线索后死循环
        _printNode(n->rchild, new_offset);
    viewNode(n, offset);
    if(n->ltag!=1) // 补丁:避免建立线索后死循环
        _printNode(n->lchild, new_offset);
}

void printTree(BitTree T) {
    _printNode(T, 0);
}

// ============== stack ===================

typedef struct {
    struct BitNode* *data;
    int* offsets;
    int maxSize;
    int top;
} BitStack ;

void initBitStack(BitStack &stack, int maxSize) {
    int size = sizeof(BitNode*)*maxSize;
    stack.data = (BitNode**)malloc(size);
    //memset(stack.data, 0, size);
    stack.offsets=(int*)malloc(sizeof(int)*maxSize);
    //
    stack.maxSize=maxSize;
    stack.top=-1;
}

bool pushBitStack(BitStack &stack, BitNode* node, int offset) {
    if(stack.top>=stack.maxSize-1) return false; // 满了
    int top=++stack.top;
    stack.data[top]=node;
    stack.offsets[top]=offset;
    return true;
}

bool pushBitStack(BitStack &stack, BitNode* node) {
    return pushBitStack(stack, node, 0);
}

bool isEmptyStack(BitStack stack) {
    return stack.top<0;
}

bool popBitStack(BitStack &stack, BitNode* &node, int &offset) {
    if(isEmptyStack(stack)) return false; // 空了
    int top=stack.top--;
    node=stack.data[top];
    offset=stack.offsets[top];
    return true;
}

bool popBitStack(BitStack &stack, BitNode* &node) {
    int offset;
    return popBitStack(stack, node, offset);
}

void freeBitStack(BitStack &stack) {
    free(stack.data);
    // stack=NULL;
    free(stack.offsets);
}

// ============== stack & tree ===================

void printTree_2(BitTree root) { // 非递归遍历
    BitStack stack;
    initBitStack(stack, 50);

    // 中序
    int offset=0;
    BitNode *p = root;
    while(p!=NULL||!isEmptyStack(stack))
    {
        if(p!=NULL)
        {
            pushBitStack(stack, p, offset++);
            p=p->lchild;
        } 
        else
        {
            popBitStack(stack, p, offset);
            viewNode(p, offset++);
            p=p->rchild;
        }
    }

    freeBitStack(stack);
}

// ============== main ===================

int main()
{
    cout << "2021年06月19日18:02:03" << endl; // ss

    // 定义空树
    BitTree root;

    // 插入根节点
    newBitNode(root, 7);
    newBitNode(root->lchild, 5);
    newBitNode(root->lchild->rchild, 6);
    newBitNode(root->lchild->lchild, 3);
    newBitNode(root->lchild->lchild->rchild, 4);
    newBitNode(root->lchild->lchild->lchild, 1);
    newBitNode(root->lchild->lchild->lchild->rchild, 2);
    newBitNode(root->rchild, 10);
    newBitNode(root->rchild->rchild, 15);
    newBitNode(root->rchild->rchild->lchild, 13);
    newBitNode(root->rchild->rchild->lchild->rchild, 14);
    newBitNode(root->rchild->rchild->lchild->lchild, 11);
    newBitNode(root->rchild->rchild->lchild->lchild->rchild, 12);
    newBitNode(root->rchild->lchild, 9);
    newBitNode(root->rchild->lchild->lchild, 8);

    // 打印
    printTree(root);
    cout << "------------------------------------" << endl;
    printTree_2(root);

    // 构建索引
    buildTreeInThread(root);
    // 打印
    cout << "------------------------------------" << endl;
    printTreeInThread(root);


    freeTree(root);

    cout << "done!" << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骆言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值