实现对二叉树的操作---插入,删除,最大(小)值,遍历,查找

你可以看完代码再看难点,或许会有更深的理解

难点:

这些操作看起来挺简单,但实现起来确实不好操作:

  1. 各种函数要考虑为空树的情况,例如:FindMax与FindMin
  2. 删除函数中,要用递归的找个删除的元素并删除,不能简单地用Find函数找到就把他删除:因为用Find函数找到这些元素后指针指向这些要删除的元素,当这些元素直接被删除时这些元素的子元素没有办法再与父节点拼接。这就会造成断链
    而当调用递归时每次调用结束都会返回新的子根节点(删除元素有两个子结点) 或者 子根结点的子结点(删除元素没有两个子结点)
进行前置工作
typedef int ElementType;
typedef struct TNode* Position;
typedef Position BinTree;
struct TNode {
    ElementType Data;
    BinTree Left;
    BinTree Right;
};

要完成的操作
void PreorderTraversal(BinTree BT); 
void InorderTraversal(BinTree BT);  

BinTree Insert(BinTree BST, ElementType X);
BinTree Delete(BinTree BST, ElementType X);
Position Find(BinTree BST, ElementType X);
Position FindMin(BinTree BST);
Position FindMax(BinTree BST);
操作实现
BinTree Insert(BinTree BST, ElementType X) {
    if (!BST) {
        BST = (BinTree)malloc(sizeof(struct TNode));
        BST->Data = X;    BST->Left = NULL;     BST->Right = NULL;
    }
    else {
        if (X > BST->Data) {
            BST->Right = Insert(BST->Right, X);
        }
        else {
            BST->Left = Insert(BST->Left, X);
        }
    }
    return BST;
}

Position FindMin(BinTree BST) {
    if (!BST)
        return NULL;
    if (BST->Left) {
        FindMin(BST->Left);
    }
    else { //这个BST没有左结点,意味着最小
        return BST;
    }
}

Position FindMax(BinTree BST) {
    if (!BST)
        return NULL;
    if (BST->Right) {
        FindMax(BST->Right);
    }
    else {
        return BST;
    }
}

Position Find(BinTree BST, ElementType X) {
    Position T = NULL;
    if (BST == NULL ) {
        T = NULL;
    }
    else{
        if (X == BST->Data) {
            T = BST;
        }
        else if (X < BST->Data) {
            T = Find(BST->Left, X);
        }
        else if (X > BST->Data) {
            T = Find(BST->Right, X);
        }
    }
    return T;
}

BinTree Delete(BinTree BST, ElementType X) { 
    if (!BST) { //BST是空
        printf("Not Found\n");
    }
    else if (X < BST->Data) {
        BST->Left = Delete(BST->Left, X);
    }
    else if (X > BST->Data) {
        BST->Right = Delete(BST->Right, X);
    }
    else {
        if (BST->Left && BST->Right) {
            BinTree M = FindMax(BST->Left);
            BST->Data = M->Data;
            BST->Left = Delete(BST->Left, M->Data);
        }
        else {
            if (BST->Left) {
                BinTree M = BST;
                BST = BST->Left;
                free(M);
            }
            else {
                BinTree M = BST;
                BST = BST->Right;
                free(M);
            }
        }
    }
    return BST;
}

void PreorderTraversal(BinTree BT) {
    if (BT) {
        printf("%d ", BT->Data);
        PreorderTraversal(BT->Left);
        PreorderTraversal(BT->Right);
    }
}
void InorderTraversal(BinTree BT) {
    if (BT) {
        InorderTraversal(BT->Left);
        printf("%d ", BT->Data);
        InorderTraversal(BT->Right);
    }
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉树的顺序存储是指将二叉树中的节点按照从上到下、从左到右的顺序依次存储到一个数组中。对于一个具有 n 个节点的二叉树,其顺序存储形式需要使用一个长度为 n+1 的数组,其中下标为 0 的位置留空,从下标为 1 的位置开始存储二叉树的根节点。 下面以前序遍历为例,介绍如何用顺序存储实现二叉树遍历操作。 首先,定义一个长度为 n+1 的数组 `tree` 来存储二叉树。数组的下标从 1 开始,对于节点 i,其左子节点的下标为 2*i,右子节点的下标为 2*i+1,父节点的下标为 i/2。 1. 前序遍历 前序遍历的顺序是先遍历根节点,再遍历左子树,最后遍历右子树。使用递归方式实现前序遍历: ```c++ void preOrder(int i) { if (i > n) return; // 递归结束条件 cout << tree[i] << " "; // 输出节点 preOrder(i*2); // 遍历左子树 preOrder(i*2+1); // 遍历右子树 } ``` 2. 中序遍历 中序遍历的顺序是先遍历左子树,再遍历根节点,最后遍历右子树。使用递归方式实现中序遍历: ```c++ void inOrder(int i) { if (i > n) return; // 递归结束条件 inOrder(i*2); // 遍历左子树 cout << tree[i] << " "; // 输出节点 inOrder(i*2+1); // 遍历右子树 } ``` 3. 后序遍历 后序遍历的顺序是先遍历左子树,再遍历右子树,最后遍历根节点。使用递归方式实现后序遍历: ```c++ void postOrder(int i) { if (i > n) return; // 递归结束条件 postOrder(i*2); // 遍历左子树 postOrder(i*2+1); // 遍历右子树 cout << tree[i] << " "; // 输出节点 } ``` 4. 层序遍历 层序遍历是按照二叉树的层次顺序依次遍历每个节点。使用队列实现层序遍历: ```c++ void levelOrder() { queue<int> q; q.push(1); // 将根节点入队 while (!q.empty()) { int i = q.front(); q.pop(); cout << tree[i] << " "; // 输出节点 if (i*2 <= n) q.push(i*2); // 将左子节点入队 if (i*2+1 <= n) q.push(i*2+1); // 将右子节点入队 } } ``` 5. 插入节点 对于顺序存储的二叉树插入节点的操作需要先找到一个空的位置,将新节点插入到该位置。如果该节点已经存在,则无法插入。 ```c++ bool insert(int x) { int i = 1; while (i <= n && tree[i] != 0) { if (x == tree[i]) return false; // 节点已经存在,插入失败 if (x < tree[i]) i = i*2; // 插入到左子树 else i = i*2+1; // 插入到右子树 } if (i > n) return false; // 插入失败,二叉树已满 tree[i] = x; // 插入节点 return true; } ``` 6. 删除节点 对于顺序存储的二叉树删除节点的操作需要将该节点以及其子树全部删除。具体操作为:将该节点的置为 0,然后递归删除其左子树和右子树。 ```c++ bool remove(int x) { int i = 1; while (i <= n && tree[i] != x) { if (x < tree[i]) i = i*2; // 查找左子树 else i = i*2+1; // 查找右子树 } if (i > n) return false; // 节点不存在,删除失败 tree[i] = 0; // 删除节点 remove(i*2); // 递归删除左子树 remove(i*2+1); // 递归删除右子树 return true; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值