设为首页 加入收藏

TOP

二叉排序树实现(C++封装)(一)
2015-02-02 14:22:46 来源: 作者: 【 】 浏览:20
Tags:排序 实现 封装

设计思路


设计一个类,根结点只可读取,具备构造二叉树、插入结点、删除结点、查找、 查找最大值、查找最小值、查找指定结点的前驱和后继等功能接口。


二叉排序树概念


它或者是一棵空树;或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树。


二叉排序树的各种操作


插入新节点
这是一个递归操作,递归设计时要找到最源头,才能得到最简设计。一种设计是判断叶子节点,把新节点作为叶子节点的孩子插入;一种是永远当作根进行插入,插入节点永远是当前子树的根!看代码:



//root为二级指针的原因是,如果树为空,需要将根修改反馈回来
bool BinaryTree::InsertNode(pNode * cuRoot, int data, pNode self)
{? //递归设计时找到最源头,才能得到最简设计
? ? if (*cuRoot == nullptr){
? ? ? ? pNode node = new Node;
? ? ? ? if (node == nullptr)
? ? ? ? ? ? return false;
? ? ? ? node->data = data;
? ? ? ? node->lChild = node->rChild = node->parent = nullptr;
? ? ? ? (*cuRoot) = node;
? ? ? ? node->parent = self;
? ? ? ? return true;
? ? }
? ? if (data > (*cuRoot)->data)
? ? ? ? InsertNode(&(*cuRoot)->rChild, data, *cuRoot);
? ? else
? ? ? ? InsertNode(&(*cuRoot)->lChild, data, *cuRoot);
? ? return true;
}


?


构造函数
一共两个重载函数:一个无参,一个接受数组利用插入函数直接构造二叉排序树。


?


BinaryTree::BinaryTree(int * datum, int len)
{
? ? root = nullptr;
? ? for (int i = 0; i < len; i++)
? ? ? ? InsertNode(&root, datum[i], root);
}


BinaryTree::BinaryTree()
{
? ? root = nullptr;
}


?


查找函数
这也是一个递归操作,为了对外隐藏root(根节点),因此编写了一个私有函数,进行真正的查找操作。


?


//真正的查找函数
BinaryTree::pNode BinaryTree::_searchKey(pNode root, int key){
? ? if (root == nullptr)
? ? ? ? return nullptr;
? ? if (root->data == key)? ? //找到了
? ? ? ? return root;
? ? else if (root->data > key)//值偏小,到左子树找
? ? ? ? return _searchKey(root->lChild, key);
? ? else? ? ? ? ? ? ? ? ? ? ? //值偏大,到右子树找
? ? ? ? return _searchKey(root->rChild, key);
}
//对外接口
BinaryTree::pNode BinaryTree::SearchKey(int key){
? ? return _searchKey(root, key);
}


?


找前驱节点
要么为左子树中最大者,要么一直追溯其父节点链,第一个是其父节点的右孩子的父节点,即为所求。


?


BinaryTree::pNode BinaryTree::SearchPredecessor(pNode node){
? ? if (node == nullptr)
? ? ? ? return nullptr;
? ? else if (node->lChild != nullptr)
? ? ? ? return SearchMaxNode(node->lChild);
? ? else
? ? {
? ? ? ? if (node->parent == nullptr)
? ? ? ? ? ? return nullptr;
? ? ? ? while (node)
? ? ? ? {
? ? ? ? ? ? if (node->parent->rChild == node)
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? node = node->parent;
? ? ? ? }
? ? ? ? return node->parent;
? ? }
}


?


找后继节点
与找前驱节点基本相似。 要么为右子树中最小者,要么一直追溯其父节点链,第一个是其父节点的左孩子的父节点,即为所求。


?


BinaryTree::pNode BinaryTree::SearchSuccessor(pNode node){
? ? if (node == nullptr)
? ? ? ? return nullptr;
? ? else if (node->rChild != nullptr)
? ? ? ? return SearchMinNode(node->rChild);
? ? else
? ? {
? ? ? ? if (node->parent == nullptr)
? ? ? ? ? ? return nullptr;
? ? ? ? while (node)
? ? ? ? {
? ? ? ? ? ? if (node->parent->lChild == node)
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? node = node->parent;
? ? ? ? }
? ? ? ? return node->parent;
? ? }
}


?


找最小值


?


BinaryTree::pNode BinaryTree::SearchMinNode(pNode curNode){
? ? if (curNode == nullptr)
? ? ? ? return nullptr;
? ? //一直找到左子树为空的节点,即为最小值
? ? while (curNode->lChild != nullptr)
? ? ? ? curNode = curNode->lChild;
? ? return curNode;
}


?


找最大值


?


BinaryTree::pNode BinaryTree::SearchMaxNode(pNode curNode){
? ? if (curNode == nullptr)
? ? ? ? return nullptr;
? ? //一直找到右子树为空的节点,即为最大值
? ? while (curNode->rChild != nullptr)
? ? ? ? curNode = curNode->rChild;
? ? return curNode;
}


?


中序遍历


?


void BinaryTree::_visitMiddle(pNode root){
? ? if (root != nullptr){
? ? ? ? _visitMiddle(root->lChild);
? ? ? ? printf("%d;", root->data);
? ? ? ? _visitMiddle(root->rChild);
? ? }
}


void BinaryTree::VisitMiddle(){
? ? _visitMiddle(root);
}


?


删除节点
这个是最麻烦的操作,分四种情况分别处理,最麻烦的是被删节点左右子树都存在的情况,这时将被删节点内容换成其后继内容,删除其后继(递归)。


?


bool BinaryTree::DeleteNode(int key){
? ? //return _deleteNode(root, key);
? ? pNode node = SearchKey(key);
? ? if (!node)
? ? ? ? return false;
? ? //被删节点

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇OpenCV使用RANSAC的仿射变换估计 .. 下一篇Linux编程中接收主函数返回值以及..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: