二叉搜索树的基本功能实现
来源:互联网 发布:nosql数据库的优势 编辑:程序博客网 时间:2024/06/06 16:34
二叉查找树(Binary Search Tree),又被称为二叉搜索树。设x为二叉查找树中的一个结点,x节点包含关键字key,节点x的key值记为key[x]。如果y是x的左子树中的一个结点,则key[y] <= key[x];如果y是x的右子树的一个结点,则key[y] >= key[x]。
在二叉查找树中:
(01) 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(02) 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(03) 任意节点的左、右子树也分别为二叉查找树。
(04) 没有键值相等的节点(no duplicate nodes)。
在实际应用中,二叉查找树的使用比较多。下面,用C语言实现二叉查找树。
我在网上查到的一位大神写的加上我自己总结的,一起分享给大家
*二叉搜索树中的节点类 *Node.h */ # ifndef _NODE_ #define _NODE_ class Node { private: int value;/*节点中存放的元素值*/ Node *parentNode;/*所指向的父节点指针*/ Node *leftChildNode;/*左孩子节点指针*/ Node *rightChildNode;/*右孩子节点指针*/ public: Node(int v);/*初始化函数*/ Node* getParentNode();/*返回父节点指针*/ Node* getLeftChildNode();/*返回左孩子节点指针*/ Node* getRightChildNode();/*返回右孩子节点指针*/ int getValue();/*返回节点元素值*/ void setParentNode(Node *p);/*设定父节点指针*/ void setLeftChildNode(Node *left);/*设定左孩子节点*/ void setRightChildNode(Node *right);/*设定右孩子结点*/ void setValue(int v);/*设定节点元素值*/ }; #endif
/* *Node.cpp */ #include "Node.h" #include <cstdio> //NULL /*初始化函数*/ Node::Node(int r) { setValue(r); setParentNode(NULL); setLeftChildNode(NULL); setRightChildNode(NULL); } /*返回父节点指针*/ Node* Node::getParentNode() { return parentNode; } /*返回右孩子节点指针*/ Node* Node::getRightChildNode() { return rightChildNode; } /*返回左孩子节点指针*/ Node* Node::getLeftChildNode() { return leftChildNode; } /*返回节点元素值*/ int Node::getValue() { return value; } /*设定左孩子节点*/ void Node::setLeftChildNode(Node *left) { leftChildNode = left; } /*设定父节点指针*/ void Node::setParentNode(Node *parent) { parentNode = parent; } /*设定右孩子结点*/ void Node::setRightChildNode(Node *right) { rightChildNode = right; } /*设定节点元素值*/ void Node::setValue(int v) { value = v; }
/*二叉搜索树类: *BinarySearchTree.h */ #ifndef _BINARYSEARCHTREE_ #define _BINARYSEARCHTREE_ #define MAXLENGTH 100 //二叉搜索树的最大节点总数 #include "Node.h" class BinarySearchTree { private: Node *rootNode;/*根节点指针*/ public: BinarySearchTree();/*构造函数初始化*/ void setRootNode(Node *root);/*设置根节点*/ void treeInsert(int v);/*向搜索数中添加节点*/ void levelTreeWalk(Node *start);/*层次遍历*/ void inorderTreeWalk(Node *start);/*中序遍历*/ void preorderTreeWalk(Node *start);/*先序遍历*/ void postorderTreeWalk(Node *start);/*后序遍历*/ void transplant(Node *u,Node *v);/*将节点v替换到u的位置,并且相应子树进行转换*/ bool deleteNode(Node *point);/*从搜索树中删除节点point*/ bool max(int x,int y);/*比较两个整型元素值大小,x<y返回false*/ int getNodeNumber(Node *start);/*得到以start为根的树的节点总数*/ int getTreeHeight();/*计算二叉搜索树的高度*/ int getNodeHeight(Node *start);/*计算节点start的高度*/ Node* getRootNode();/*得到根节点指针*/ Node* getMinimum(Node *start);/*得到以start节点为根的搜索数中的具有最小元素值的节点*/ Node* treeMax(Node *start);//递归版本的得到具有最大元素值的节点 Node* getMaximum(Node *start);/*得到以start为根节点的搜索数中的具有最大元素值的节点*/ Node* getTreeSuccessor(Node *start);/*得到节点start的后继节点*/ Node* getTreePredessor(Node *start);/*得到start的前驱节点*/ Node* treeSearch2(Node *start,int k);/*迭代版本*/ Node* treeSearch1(Node *start,int k);/*搜索数的查找,如果k存在于搜索树中, (从树根开始查找,)则返回给节点,否则返回null*/ }; #endif
/* *BinarySearchTree.cpp */ #include "BinarySearchTree.h" #include <cstdio> #include <iostream> using namespace std; /*构造函数初始化*/ BinarySearchTree::BinarySearchTree() { setRootNode(NULL); } /*得到根节点指针*/ Node* BinarySearchTree::getRootNode() { return rootNode; } /*设置根节点*/ void BinarySearchTree::setRootNode(Node *root) { rootNode = root; } /*向搜索数中添加节点,输入是新的节点元素值*/ void BinarySearchTree::treeInsert(int v) { /*新的插入的节点*/ Node *newInsertNode = new Node(v); Node *y = NULL; Node *x = getRootNode();//得到根节点 /*通过while循环中元素比较得到新的节点的合适位置*/ while(x!=NULL) { y = x; if(v < x->getValue()) /*二叉搜索树的性质:x.left.value<x.value;*/ x = x->getLeftChildNode(); else /*x.right.value>=x.values*/ x = x->getRightChildNode(); } //y = newInsertNode; if(y == NULL)//二叉搜索树为空的情况 setRootNode(newInsertNode); else if(v < y->getValue()) { y->setLeftChildNode(newInsertNode); newInsertNode->setParentNode(y); } else { y->setRightChildNode(newInsertNode); newInsertNode->setParentNode(y); } } /*从搜索树中删除节点point,如果删除成功,返回true, 如果是空子树,返回false*/ /*1、point没有左右子孩子,直接删除point *2、point没有左孩子的情况,直接删除point并把右孩子放到原来point位置 上面两种情况可以归为一类情况:没有左孩子,将右孩子放到point位置 3、只有左孩子情况,把左孩子放到point位置,删除point 4、左右孩子都有的情况:查找point节点的后继节点successor 1、如果successor为point右孩子(既然为point右孩子,则successsor没有左孩子) 将point左孩子作为successor左孩子,successor替换point,删除point节点 2、如果successor不是point的右孩子(是以point右孩子为根节点的子树最小值所在节点 且没有左孩子)将successor右节点sright作为successor所在子树根节点,并将point 右孩子节点pright作为successor右节点,successor左孩子节点pleft作为successor 左孩子节点,删除point,,, */ bool BinarySearchTree::deleteNode(Node *point) { /*搜索树为空或point为空时进行的操作*/ if(point == NULL || getRootNode() == NULL) return false; /*如果节点point不再搜索树中*/ if(treeSearch1(getRootNode(),point->getValue()) == NULL) return false; /*下面的就是讨论的三种情况:*************************/ /*1、point的左孩子节点为空*/ if(point->getLeftChildNode() == NULL) transplant(point,point->getRightChildNode()); /*2、point的右孩子节点为空*/ else if(point->getRightChildNode() == NULL) transplant(point,point->getLeftChildNode()); /*3、point的左右孩子节点均不为空*/ else { /*得到point的后继节点*/ Node *successor = getMinimum(point->getRightChildNode()); /*当successor不为point的右孩子节点时进行的操作*/ if(successor->getParentNode() != point) { transplant(successor,successor->getRightChildNode()); successor->setRightChildNode(point->getRightChildNode()); successor->getRightChildNode()->setParentNode(successor); } transplant(point,successor); successor->setLeftChildNode(point->getLeftChildNode()); successor->getLeftChildNode()->setParentNode(successor); } delete point; return true; } /*此时u节点右节点为空,v节点左孩子为空,将u的左孩子节点放到v的左孩子节点处 并把u的父节点作为v的父节点,即删除u节点 此函数的作用是将u的父节点作为v的父节点,v作为u的父节点的原u位置相应子节点 v可以为空节点,也可以不是,对于u的左孩子节点的处理,由这个函数的调用者进行 处理 */ void BinarySearchTree::transplant(Node *u,Node *v) { if(u->getParentNode() == NULL) setRootNode(v); else if(u == u->getParentNode()->getLeftChildNode()) u->getParentNode()->setLeftChildNode(v); else u->getParentNode()->setRightChildNode(v); if(v != NULL) v->setParentNode(u->getParentNode()); } /*得到以start节点为根的搜索数中的具有最小元素值的节点*/ /*while迭代版本:*/ Node* BinarySearchTree::getMinimum(Node *start) { Node *minNode = start; if(minNode == NULL)//空树的情况 return minNode; while(minNode->getLeftChildNode() != NULL) { minNode = minNode->getLeftChildNode(); } return minNode; } /*得到以start为根节点的搜索数中的具有最大元素值的节点*/ /*递归版本:*/ Node* BinarySearchTree::getMaximum(Node *start) { return treeMax(start); } Node* BinarySearchTree::treeMax(Node *start) { if(start == NULL) return NULL; else if(start->getRightChildNode() == NULL) return start; else return treeMax(start->getRightChildNode()); } /*得到以start为根的树的节点总数*/ int BinarySearchTree::getNodeNumber(Node *start) { if(start == NULL) return 0; if(start->getLeftChildNode() ==NULL) return getNodeNumber(start->getRightChildNode()) + 1; if(start->getRightChildNode() == NULL) return getNodeNumber(start->getLeftChildNode()) + 1; return getNodeNumber(start->getLeftChildNode()) + getNodeNumber(start->getRightChildNode()) + 1; } /*层次遍历*/ void BinarySearchTree::levelTreeWalk(Node *start) { if(start == NULL) { cout << "这是一个空子树," << endl; return; } /*定义一个数组来存放层次遍历过程中的节点指针,最大为MAXLENGTH*/ Node *B[MAXLENGTH + 1]; B[1] = start;/*根节点放到B[1]处*/ int nodeNumber = getNodeNumber(start);/*树中节点个数*/ int counter = 1;//已经放到数组B中的节点个数 int k = 1;/*在之后的每次循环中,counter之前有k个节点需要得到子节点放入数组B*/ int m,i;//寄存器值 while(counter < nodeNumber) { m = 0; /*循环得到counter之前的k个节点它们的子节点*/ for(i = 1;i <= k;i ++)//k其实就是每一层中的节点个数 { if(B[counter-k+i]->getLeftChildNode() != NULL) { m ++; B[counter + m] = B[counter-k+i]->getLeftChildNode(); } if(B[counter-k+i]->getRightChildNode() != NULL) { m ++; B[counter + m] = B[counter-k+i]->getRightChildNode(); } } k = m; counter = counter + k; } for(i = 1;i <= nodeNumber;i++) cout << B[i]->getValue() << " "; } /*中序遍历:<<<<左根右>>>>*/ void BinarySearchTree::inorderTreeWalk(Node *start) { if(start != NULL) { inorderTreeWalk(start->getLeftChildNode()); cout << start->getValue() << " "; inorderTreeWalk(start->getRightChildNode()); } } /*先序遍历:<<<<根左右>>>>*/ void BinarySearchTree::preorderTreeWalk(Node *start) { if(start != NULL) { cout << start->getValue() << " "; preorderTreeWalk(start->getLeftChildNode()); preorderTreeWalk(start->getRightChildNode()); } } /*后序遍历:<<<<左右根>>>>*/ void BinarySearchTree::postorderTreeWalk(Node *start) { if(start != NULL) { preorderTreeWalk(start->getLeftChildNode()); preorderTreeWalk(start->getRightChildNode()); cout << start->getValue() << " "; } } /*计算二叉搜索树的高度*/ int BinarySearchTree::getTreeHeight() { return getNodeHeight(getRootNode()) - 1; } /*计算节点start的高度*/ int BinarySearchTree::getNodeHeight(Node *start) { if(start == NULL) return 0; int leftChildLength = getNodeHeight(start->getLeftChildNode()); int rightChildLength = getNodeHeight(start->getRightChildNode()); /*这两个判断语句是把递归进行到二叉树的叶子节点进行判断并把 叶子节点的高度(本来为0)加一*/ if(max(leftChildLength,rightChildLength)) return leftChildLength + 1; else return rightChildLength + 1; } /*比较两个整型元素值大小,x<y返回false,x>=y返回true*/ bool BinarySearchTree::max(int x,int y) { if(x >= y) return true; else return false; } /*得到节点start的后继节点,如果后继节点存在,则返回, 如果后继节点为自身,则返回null*/ Node* BinarySearchTree::getTreeSuccessor(Node *start) { if(start->getRightChildNode() != NULL) return getMinimum(start->getRightChildNode()); Node *y = start->getParentNode();//叶子节点的情况 /*仍是二叉搜索树的性质决定*/ while(y != NULL && start == y->getRightChildNode ()) { start = y; y = y->getParentNode(); } return y; } /*得到start的前驱节点如果前驱节点存在,则返回,如果前驱节点 为自身,则返回null*/ Node* BinarySearchTree::getTreePredessor(Node *start) { if(start->getLeftChildNode() != NULL) return getMaximum(start->getLeftChildNode()); Node *y = start->getParentNode(); while(y != NULL && start == y->getRightChildNode()) { start = y; y = y->getParentNode(); } return y; } /*搜索数的查找,如果k存在于搜索树中,则返回给节点,否则返回null*/ Node* BinarySearchTree::treeSearch1(Node *start,int k) { Node *temp = start; if(temp == NULL || k == temp->getValue()) return temp; if(k < start->getValue()) return treeSearch1(temp->getLeftChildNode(),k); else return treeSearch1(temp->getRightChildNode(),k); } /*搜索的while迭代版本*/ Node* BinarySearchTree::treeSearch2(Node *start,int k) { Node *temp = start; while(temp != NULL && k != temp->getValue()) { if(k < temp->getValue()) temp = temp->getLeftChildNode(); else temp = temp->getRightChildNode(); } return temp; }
0 0
- 二叉搜索树的基本功能实现
- 二叉搜索树基本功能实现
- 二叉搜索树基本功能实现
- 搜索二叉树基本功能实现(源代码)
- 二叉树的基本功能实现
- 二叉搜索树的基本功能的实现(递归及非递归直线插入,删除,查找)
- 二叉树的基本功能实现(c++)
- 数据结构(10):二叉树基本功能的实现
- java--实现二叉树的一些基本功能
- PHP实现排序二叉树的基本功能
- 二叉树基本功能的汇集(C++类实现)
- 二叉搜索树的实现
- 二叉搜索树的实现
- 二叉搜索树的实现
- 二叉搜索树的实现
- 搜索二叉树的实现
- 二叉搜索树的实现
- 二叉搜索树的实现
- linux目录结构
- js移动端树型列表
- Linux下Tomcat启动正常但无法访问
- oscache基础(一)
- hdoj 5092 Seam Carving
- 二叉搜索树的基本功能实现
- Tivoli Workload Scheduler (TWS)
- 求解偏微分方程开源有限元软件deal.II学习--Step 9
- 本地文件上传到指定目录
- Windows ISO镜像资源专用下载工具(Windows ISO Downloader) v4.0 绿色免费版
- iOS开发中如何设置textfield输入长度并且仅仅只能输入数字
- Java中在超文本协议中客户端对服务端的请求
- 六大设计原则之里氏替换原则
- Python中使用rrdtool结合Django进行带宽监控