二叉排序树节点的删除(C++,算法导论),前中后序遍历(递归/非递归,栈实现),按层次遍历(队列实现)
2016-05-31 20:08
525 查看
由于代码中包含了二叉树,栈,队列三种结构的实现,为了文件结构更清晰,我会列出各文件名以及它们各自所实现的功能。
栈和队列只是为二叉树而创建的,所以它们的头文件只是实现了最基本的函数,如压栈,出栈,入队列,出队列,获取节点元素……
二叉树实现了节点插入和删除,数据搜索按照算法导论一书而来;先序,中序,后序的递归和非递归算法,非递归算法使用栈实现;按层次遍历用队列实现。
栈,队列和二叉树均采用了类模板,而栈和队列的节点当中存放的是二叉树的节点,所以如果你想看懂下面的代码,最好知道类模板的用法。在完成这些代码之前,我对类模板还停留在一知半解的层面,但是完成了它们之后,才逐渐明白了一些类模板的妙处。
栈的实现头文件:Stack.h
#ifndef STACK_H_INCLUDED #define STACK_H_INCLUDED #include <iostream> using namespace std; template<class T> struct Stack_Node { T Date; Stack_Node* Next_Node; Stack_Node(T date=0) { Date=date; Next_Node=NULL; } }; template<class T> class Stack { int Node_Count; Stack_Node<T>* Top_Point; public: Stack(int node_count=0) { Node_Count=node_count; Top_Point=NULL; } ~Stack() { Clear_Stack(); } Stack_Node<T>* Get_Top() { return Top_Point; } int Get_Node_count() { return Node_Count; } void Print_Stack()//从栈顶开始输出,测试所用函数 { Stack_Node<T>*p=Top_Point; while(p!=NULL) {//如果不是系统定义类型,比如类,下句cout则无法输出。 cout<<p->Date<<" "; if(p->Next_Node==NULL) return; p=p->Next_Node; } } void Push_Stack_Node(T date)//节点入栈顶 { Stack_Node<T>*p=new Stack_Node<T>(date); p->Next_Node=Top_Point; Top_Point=p; Node_Count++; } bool Popup_Stack_Node()//弹出栈顶节点 { if(Node_Count<=0) return false; Stack_Node<T>*p=Top_Point; Top_Point=Top_Point->Next_Node; delete p; Node_Count--; } T Get_Top_Date()//获取栈顶元素 { return Top_Point->Date; } void Clear_Stack()//清空栈 { for(int i=1; i<=Node_Count; i++) { Stack_Node<T>*p=Top_Point; Top_Point=Top_Point->Next_Node; delete p; } Node_Count=0; } }; #endif // STACK_H_INCLUDED
队列的实现:Queue.h
#ifndef QUEUE_H_INCLUDED #define QUEUE_H_INCLUDED #include <iostream> using namespace std; template<class T> struct Queue_Node { T Date; Queue_Node* Next_Node; Queue_Node(T date=0) { Date=date; Next_Node=NULL; } }; template<class T> class Queue { int Node_Count; Queue_Node<T>* Head_Point; Queue_Node<T>* Tail_Point; public: Queue(int node_count=0) { Node_Count=node_count; Head_Point=NULL; Tail_Point=NULL; } ~Queue() { Clear_Queue(); } Queue_Node<T>* Get_Head() { return Head_Point; } T Get_Head_Date() { return Head_Point->Date; } int Get_Node_count() { return Node_Count; } void Print_Queue()//队列的输出 { Queue_Node<T>*p=Head_Point; while(p!=NULL) { cout<<p->Date<<" "; if(p->Next_Node==NULL) return; p=p->Next_Node; } } void Push_Queue_Node(T date)//队列尾部插入元素 { Queue_Node<T>*p=new Queue_Node<T>(date); if(Node_Count==0) { Head_Point=p; Tail_Point=p; Node_Count++; return; } Tail_Point->Next_Node=p; Tail_Point=Tail_Point->Next_Node; Node_Count++; } bool Popup_Queue_Node()//队列头部插入元素 { if(Node_Count<=0) return false; Queue_Node<T>*p=Head_Point; Head_Point=Head_Point->Next_Node; delete p; Node_Count--; } void Clear_Queue()//清空队列 { for(int i=1; i<=Node_Count; i++) { Queue_Node<T>*p=Head_Point; Head_Point=Head_Point->Next_Node; delete p; } Node_Count=0; } }; #endif // QUEUE_H_INCLUDED
二叉树的实现:Bnary_Trees.h
#ifndef BINARY_TREES_H_INCLUDED #define BINARY_TREES_H_INCLUDED #include <iostream> #include"Stack.h" #include"Queue.h" using namespace std; template<class T> struct Trees_node { T Date; Trees_node* Left_Children; Trees_node* Right_Children; Trees_node(T date=0) { Date=date; Left_Children=NULL; Right_Children=NULL; } }; template<class T> class Binary_Trees { Trees_node<T> *Root_Point; public: Binary_Trees(T date=0) { Root_Point=new Trees_node<T>(date); } Trees_node<T> * Get_Root() { return Root_Point; } T Get_Date(Trees_node<T> *node) { return node->Date; } //获得子二叉树的最小值的指针 Trees_node<T>* Get_Minimum(Trees_node<T>* p) { while(p->Left_Children!=NULL) { p=p->Left_Children; } return p; } //获得子二叉树的最大值的指针 Trees_node<T>* Get_Maximum(Trees_node<T>* p) { while(p->Right_Children!=NULL) { p=p->Right_Children; } return p; } //先序遍历递归算法 void Pre_Print_Trees_Re(Trees_node<T> *node) { if(node) { cout<<node->Date<<" "; Pre_Print_Trees_Re(node->Left_Children); Pre_Print_Trees_Re(node->Right_Children); } } //先序遍历非递归算法,栈实现 void Pre_Print_Trees() { Trees_node<T>*p=Root_Point; Stack<Trees_node<int>*> Pre; while(p!=NULL||Pre.Get_Node_count()) { if(p!=NULL) { cout<<p->Date<<" "; Pre.Push_Stack_Node(p); p=p->Left_Children; } else { p=Pre.Get_Top_Date(); Pre.Popup_Stack_Node(); p=p->Right_Children; } } } //中序遍历递归算法 void In_Print_Trees_Re(Trees_node<T> *root_node) { if(root_node) { In_Print_Trees_Re(root_node->Left_Children); cout<<root_node->Date<<" "; In_Print_Trees_Re(root_node->Right_Children); } } //中序遍历非递归算法,栈实现 void In_Print_Trees() { Trees_node<T>*p=Root_Point; Stack<Trees_node<int>*> In; while(p!=NULL||In.Get_Node_count()) { if(p!=NULL) { In.Push_Stack_Node(p); p=p->Left_Children; } else { p=In.Get_Top_Date(); In.Popup_Stack_Node(); cout<<p->Date<<" "; p=p->Right_Children; } } } //后序遍历递归算法 void Post_Print_Trees_Re(Trees_node<T> *root_node) { if(root_node) { In_Print_Trees_Re(root_node->Left_Children); In_Print_Trees_Re(root_node->Right_Children); cout<<root_node->Date<<" "; } } //后序遍历非递归算法,栈实现 void Post_Print_Trees() { Stack<Trees_node<int>*> Post,Read; Post.Push_Stack_Node(Root_Point); while (Post.Get_Node_count()) { Trees_node<T> *p = Post.Get_Top_Date(); Post.Popup_Stack_Node(); Read.Push_Stack_Node(p);//逆序压入栈中 if (p->Left_Children) Post.Push_Stack_Node(p->Left_Children); if (p->Right_Children) Post.Push_Stack_Node(p->Right_Children); } while(Read.Get_Node_count()) { cout<<Get_Date(Read.Get_Top_Date())<<" "; Read.Popup_Stack_Node(); } } //按层次遍历,队列实现 void Layer_Print_Trees() { if (Root_Point == NULL) return ; Trees_node<T> *p = Root_Point; Queue<Trees_node<T> *> Layer; Layer.Push_Queue_Node(p); while(Layer.Get_Node_count()) { p=Layer.Get_Head_Date(); Layer.Popup_Queue_Node(); cout<<p->Date<<" "; if (p->Left_Children) Layer.Push_Queue_Node(p->Left_Children); if (p->Right_Children) Layer.Push_Queue_Node(p->Right_Children); } } //搜索数据的递归方法 Trees_node<T>* Search_Node_Re(Trees_node<T> *root_node,T date) { if(root_node==NULL||root_node->Date==date) return root_node; if(date<root_node->Date) return Search_Node(root_node->Left_Children,date); else return Search_Node(root_node->Right_Children,date); } //搜索数据的非递归方法 Trees_node<T>* Search_Node(Trees_node<T> *root_node,T date) {//如果没有找到节点,返回空的指针,可以用于bool判断 while(root_node!=NULL&&root_node->Date!=date) { if(date<root_node->Date) root_node=root_node->Left_Children; else root_node=root_node->Right_Children; } return root_node; } bool Insert_Node(T date) { Trees_node<T> *q,*p,*r; p=new Trees_node<T>(date); q=NULL; r=Root_Point; while(r!=NULL) { q=r; if(date<r->Date) r=r->Left_Children; else if(date>r->Date) r=r->Right_Children; else//if(date=r->Date) return false; } if(q==NULL) Root_Point=p; else if(date<q->Date) q->Left_Children=p; else q->Right_Children=p; return true; } //删除节点的辅助函数 void Trans_Plant(Trees_node<T> *delete_parent,Trees_node<T> *delete_node,Trees_node<T> * replace_node) { if(delete_parent==NULL) Root_Point=replace_node; else if(delete_node==delete_parent->Left_Children) delete_parent->Left_Children=replace_node; else //if(delete_node==delete_parent->Right_Children) delete_parent->Right_Children=replace_node; } //删除节点是根据算法导论而写,四种情况的分析 bool Delete_Node(T date) { Trees_node<T> *delete_parent=NULL; Trees_node<T> *delete_node=Root_Point; Trees_node<T> *replace_parent; Trees_node<T> *replace_node; while(delete_node!=NULL&&delete_node->Date!=date)//查找删除节点以及它的双亲节点 { delete_parent=delete_node; if(date<delete_node->Date) delete_node=delete_node->Left_Children; else delete_node=delete_node->Right_Children; } if(!delete_node) return false;//如果没有该节点,返回Error if(delete_node->Left_Children==NULL)//处理了两种情况,无孩子和只有右孩子 Trans_Plant(delete_parent,delete_node,delete_node->Right_Children); else if(delete_node->Right_Children==NULL)//处理只有左孩子的情况 Trans_Plant(delete_parent,delete_node,delete_node->Left_Children); else //if(delete_node->Left_Children!=NULL&&delete_node->Left_Children!=NULL) {//处理有左右孩子的情况 replace_node=delete_node->Right_Children; replace_parent=delete_node; while(replace_node->Left_Children!=NULL)//代替被删除节点只能是它的前驱节点或者后继节点, { //这儿查找它的后继节点作为替补,前驱和后继指的是中序遍历的前后节点 replace_parent=replace_node; replace_node=replace_node->Left_Children; } if(delete_node!=replace_parent) //替换节点不是删除节点的孩子节点 { Trans_Plant(delete_parent,replace_node,replace_node->Right_Children); replace_node->Right_Children=delete_node->Right_Children; } Trans_Plant(delete_parent,delete_node,replace_node); replace_node->Left_Children=delete_node->Left_Children; } return true; } }; #endif // BINARY_TREES_H_INCLUDED
测试文件如下:main.cpp
#include <iostream> #include"Binary_Trees.h" using namespace std; int main() { cout<<"二叉树的测试如下:"<<endl<<endl; Binary_Trees< int> Test(5); Test.Insert_Node(4); Test.Insert_Node(6); Test.Insert_Node(9); Test.Insert_Node(7); Test.Insert_Node(8); Test.Insert_Node(2); Test.Insert_Node(9); Test.Insert_Node(10); Test.Insert_Node(3); Test.Insert_Node(1); Test.Layer_Print_Trees(); cout<<endl; if(Test.Search_Node(Test.Get_Root(),3)) { cout<<"Find!"; } else { cout<<"Not Find!"; } cout<<Test.Get_Date(Test.Get_Maximum(Test.Get_Root())); cout<<endl; Test.Delete_Node(1); // Test.In_Print_Trees_Re(Test.Get_Root()); cout<<endl; cout<<Test.Get_Date(Test.Get_Root()); cout<<endl; cout<<"栈的测试如下:"<<endl<<endl; Stack<int> Test1; Test1.Push_Stack_Node(1); Test1.Push_Stack_Node(2); Test1.Push_Stack_Node(4); Test1.Print_Stack(); cout<<endl; Test1.Popup_Stack_Node(); // Test1.Popup_Stack_Node(); // Test1.Popup_Stack_Node(); //Test1.Clear_Stack(); cout<<Test1.Get_Top_Date(); Test1.Print_Stack(); cout<<endl; cout<<"队列的测试如下:"<<endl<<endl; Queue<int> Test2; Test2.Push_Queue_Node(5); Test2.Push_Queue_Node(8); Test2.Push_Queue_Node(9); Test2.Print_Queue(); cout<<endl; Test2.Popup_Queue_Node(); // Test2.Print_Queue(); // Test2.Clear_Queue(); Test2.Push_Queue_Node(8); Test2.Push_Queue_Node(5); Test2.Push_Queue_Node(8); Test2.Push_Queue_Node(9); // Test2.Clear_Queue(); Test2.Print_Queue(); cout<<endl; return 0; }
相关文章推荐
- 二叉查找树
- 深入遍历二叉树的各种操作详解(非递归遍历)
- PHP递归遍历多维数组实现无限分类的方法
- 详解Java二叉排序树
- 了解java中的堆和栈及其优势和创建方法
- PHP递归遍历多维数组实现无限分类的方法
- 二叉树的性质以及二叉树的遍历(非递归)(c语言)(一)
- 关于图的深度优先的递归和非递归算法
- 二叉树的递归遍历
- 合并两个二叉排序树(二叉查找树)到一个数组中
- 黑马程序员——java小结_003_堆和栈
- 二叉树基本操作
- 堆和栈的区别(很经典的,正在研究中)
- 细谈java中的堆和栈
- C++学习笔记->堆和栈的区别以及各个区的划分
- 一个先序或后序序列 还原唯一 二叉排序树 (C语言实现)
- 二叉树的非递归遍历
- 二叉查找树(二叉排序树、有序二叉树)算法分析及实现
- 二叉排序树相关操作
- java二叉树的创建,遍历及其他方法