二叉搜索树及其相关操作

匿名 (未验证) 提交于 2019-12-03 00:30:01
  • 二叉树(binary tree)是一种树型数据结构,其中它的每个节点最多有两个孩子(可以没有,也可以只有一个)。
  • 二叉搜索树(binary search tree)是一种特殊的二叉树,对每个节点,其左孩子/左子树的关键字值该节点的关键字值;其右孩子/右子树的关键字值都大于该节点的关键字值。
  • 二叉搜索树的平均深度为O(logN)。其中,N为节点总数。
  • 二叉搜索树的主要操作有:创建(初始化)二叉树,查找关键字Find,返回最大最小关键字FindMax, FindMin,向树中插入元素Insert,删除节点Delete,遍历二叉树。
  • 涉及到二叉树的操作有两种方法实现:递归实现和非递归实现。


一、二叉(搜索)基本数据结构

  • 树是由一个个节点构成,节点的构成成一般为:该节点包含的关键字值(data),left指针指向其左孩子,right指针指向其右孩子。
  • 节点结构的一般声明如下:
typedef struct _TreeNode {  // 定义二叉查找树的结构     ElemType data;          // 数据     struct _TreeNode* left;         // 指向左孩子指针     struct _TreeNode* right;        // 指向其右孩子指针  }TreeNode, *SearchBTree;    // TreeNode表示节点别称,*SearchBTree表示一个指向树(子树)根节点的指针

二、初始化树

  • 一般初始化树为一个(TreeNode类型的)空指针
  • 初始化树可以和树的销毁工作合并成MakeEmpty()函数,递归地实现如下。
SearchBTree EmptyTree(SearchBTree T)    // 初始化、构造一颗空树/销毁一颗树 {     if (!T)     {         EmptyTree(T->left);     // 递归地释放空间         EmptyTree(T->right);         delete T;     }     return nullptr; }

  • 根据树的结构特点,比较要插入元素X值与节点关键字的大小,递归地插入(一般递归实现比较简单)。
  • 当X值小于某个节点的值,则递归地往其左子树中插入X;当X值大于某个节点的值,则递归地往其右子树中插入X。
  • 递归的终止条件是节点为空,申请一个新节点关键字为X插入到树中。
void Insert(SearchBTree &T, ElemType x) {     if (!T)     {         TreeNode* pT = new TreeNode;        // 申请节点空间         pT->data = x;                       // 为节点赋值         pT->left = pT->right = nullptr;         T = pT;                             // 将pT赋给T     }     else     {         if (x < T->data)                // 如果x小于某个结点的数据             Insert(T->left, x);         // 递归地在其左子树上寻找空结点插入         else if (x > T->data)           // 如果x大于某个结点的数据             Insert(T->right, x);        // 递归地在其左子树上寻找空结点插入     } }

  • 在树中查找某个关键字值,并返回其所在节点。
  • 递归地进行:从根节点开始,当前节点大于其查找的值,则递归地再其左子树中查找。否则,在其右子树中递归地查找。
  • 递归终止的条件是:查找到该关键字所在节点并返回。返回空结点,表示树中没有要查找的关键字值。
TreeNode* Find(SearchBTree T, ElemType x)   // 查找树中是否有值x {     if (T == nullptr)           // 没有找到,返回空指针         return nullptr;     if (x < T->data)            // 递归查找         return Find(T->left, x);     else if (x > T->data)         return Find(T->right, x);     else         return T;               // 查找到了,则返回T指针 }
  • 查找树中的最小值
  • 1.递归实现:递归地查找其左子树。
TreeNode* FindMin(SearchBTree T)    // 查找最小值,递归实现 {     if (T->left == nullptr)         return T;     else         return FindMin(T->left); }
  • 2.非递归实现:从根节点开始,循环遍历每个结点的左孩子,发现左孩子为空,则停止并返回该结点。
TreeNode* FindMin2(SearchBTree T)   // 查找最小值,非递归实现 {     while (T->left != nullptr)         T = T->left;     return T; }
  • 查找树中的最大值
  • 递归实现:递归地查找其右子树。
TreeNode* FindMax(SearchBTree T)    // 查找最大值 {     if (T->right == nullptr)         return T;     else         return FindMax(T->right); }

  • 分两种情况:
  • 1.删除的节点是树叶节点(没孩子):则直接删除。
  • 2.删除的节点是(子树的)根节点:也分两种情况:① 该节点有一个孩子,则直接替换为其孩子节点,然后删除释放其自身。
  • ② 该节点有两个孩子,先把该节点的关键字值替换为其右子树的最左边孩子的关键字值(最小值)。然后再删除其右子树自身的最小值。
void Delete(SearchBTree &T, ElemType x)     // 删除指定元素 {     TreeNode *tmpNode = new TreeNode;   // 创建一个临时结点     if (T == nullptr)           // 没有x存在         cout << "404 Not Found\n";     else if (x < T->data)       // x小于某个结点值         Delete(T->left, x);     // 递归地从其左子树删除x     else if (x > T->data)       // x大于某个结点的值         Delete(T->right, x);    // 递归地从其右子树删除x     else                        // 找到了x     {         if (T->left&&T->right)  // x所在结点有两个孩子的情况         {             tmpNode = FindMin(T->right);        // 将临时结点赋值为其右子树中具有最小值的结点(即最左端的结点)             T->data = tmpNode->data;            // 移动数据至要删除的目标结点             Delete(T->right, tmpNode->data);    // 删除其右子树中值为x的结点         }         else         {   // x所在结点只有一个孩子和没有孩子的情况             tmpNode = T;        // 要删除的结点T赋给临时结点tmpNode             if (T->left == nullptr)     // 若当前结点的左孩子为空                 T = T->right;           // 则,将当前结点赋值为其右孩子             else if (T->right == nullptr)   // 若当前结点的右孩子为空                 T = T->left;                // 则,将当前结点赋值为其左孩子             else                 delete tmpNode;             // 否则当前结点为叶子结点(没有孩子),则直接释放         }     } }

  • 二叉搜索树主要有三种遍历方式:先根(序)遍历,中根(序)遍历,后根(序)遍历
  • 1.先根遍历:先访问根节点,再递归地遍历其左子树,最后再递归地遍历其右子树
void PreorderPrint(SearchBTree T)       // 先根(序)遍历二叉树并打印出结点值 {     if (T != nullptr)     {         cout << T->data << " ";         PreorderPrint(T->left);         PreorderPrint(T->right);     } }
  • 1.中根遍历:先递归地遍历其左子树,然后再访问根节点,最后再递归地遍历其右子树
void InorderPrint(SearchBTree T)        // 中根(序)遍历二叉树并打印出结点值 {     if (T != nullptr)     {         InorderPrint(T->left);         cout << T->data << " ";         InorderPrint(T->right);     } }
  • 3.后根遍历:先递归地遍历其左子树,再递归地遍历其右子树,最后再访问根节点
void PostorderPrint(SearchBTree T)      // 中根(序)遍历二叉树并打印出结点值 {     if (T != nullptr)     {         PostorderPrint(T->left);         PostorderPrint(T->right);         cout << T->data << " ";     } }

int main() {     const ElemType rawdata[] = { 19, 7, 9, 15, 23, 39, 4, 2, 75, 100, 43, 58 };     SearchBTree myTree = new TreeNode;     myTree = EmptyTree(myTree);     // 初始化树     for (int i = 0;i < sizeof(rawdata) / sizeof(ElemType);i++)     {         Insert(myTree, rawdata[i]);     // 向树中插入给定数据     }     cout << "The preorder print of the tree is: \n";     PreorderPrint(myTree);     cout << endl;     cout << "The inorder print of the tree is: \n";     InorderPrint(myTree);     cout << endl;     cout << "The postorder print of the tree is: \n";     PostorderPrint(myTree);     cout << endl;     cout << "Input a value: ";     ElemType x;     cin >> x;     if (Find(myTree, x))         cout << x << "is in the tree.\n";     else         cout << x << "is not in the tree.\n";      TreeNode* TmpNode = new TreeNode;     TmpNode = FindMin(myTree);     cout << "The minimum value in the tree is: " << TmpNode->data << endl;     TmpNode = FindMax(myTree);     cout << "The maximum value in the tree is: " << TmpNode->data << endl;     cout << "Input a value to delete: ";     cin >> x;     Delete(myTree, x);     cout << "Now, the inorder print of the tree is: \n";     InorderPrint(myTree);     cout << "\nDestroy the tree..." << endl;     EmptyTree(myTree);     system("pause");     return 0; }
The preorder print of the tree is: 19 7 4 2 9 15 23 39 75 43 58 100 The inorder print of the tree is: 2 4 7 9 15 19 23 39 43 58 75 100 The postorder print of the tree is: 2 4 15 9 7 58 43 100 75 39 23 19 Input a value to search: 13 13 is not in the tree. The minimum value in the tree is: 2 The maximum value in the tree is: 100 Input a value to delete: 58 Now, the inorder print of the tree is: 2 4 7 9 15 19 23 39 43 75 100 Destroy the tree...
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!