《算法导论》学习笔记--第十二章 二叉查找树

查找树以一种数据结构,它支持多种动态集合操作,包括search,minimum,maximum,predecessor,successor,insert以及delete,它既可以用作字典,也可以用作优先队列。

二叉查找树的执行的基本操作的时间与树的高度成正比。对于一棵含有n个结点的完全二叉树,这些操作的最坏情况运行时间俄为O(lgn)。

二叉查找树

二叉查找树实现

二叉查找树定义:1、关键字不同唯一 2、左子树关键字小于根节点 3、右子树关键字大于根节点 4 左右子树也是一棵排序二叉树

  注:在实际应用中右子树可也以大于等于根节点

堆:不能删除任意元素,查找时间复杂度n,当插入、删除、查找时 二叉排序树结构最好

二叉查找树基本操作:查找 插入 删除


(需要详细学习请参考《算法导论》第十二章-二叉查找树,本代码根据算法导论实现,参照学习效果更佳 )

1.二叉查找树

 一棵二叉查找树是按二叉树结构来组织的。可以用链表结构来表示,每个结点就是一个对象。节点中有key,lchild(左子树),rchild(右子树)

定义结点:

#ifndef __TREENODE_H__
#define __TREENODE_H__

template<class Element>
class CTreeNode
{
	/*
	定义了结点的key,以及左子树和右子树。并初始化为空
	*/
		public:
			Element key;
			CTreeNode<Element> *lchild;
			CTreeNode<Element> *rchild;	
			CTreeNode(Element value):key(value),lchild(NULL),rchild(NULL){};
			
			~CTreeNode(){lchild = NULL ; rchild = NULL;};
};

#endif

操作:

 

#include "treeNode.h"

#ifndef __BINARYTREE_H__
#define __BINARYTREE_H__


    template<class Element>
    class CBinaryTree
	{
		public:
			CBinaryTree();
			~CBinaryTree();
			bool treeEmpty();          //判断树是否为空
			bool insertElement(Element value);   //插入元素
			void inorderTree(CTreeNode<Element> *root);   //中序遍历
			CTreeNode<Element> * minValue(CTreeNode<Element> * root); //返回最小值节点
			CTreeNode<Element> * maxValue(CTreeNode<Element> * root); //返回最大值节点
			CTreeNode<Element> * search(Element value);  //查找元素
			bool deleteValue(Element value);    //删除元素
			CTreeNode<Element> * parent(CTreeNode<Element> * child);  //查找父节点
			CTreeNode<Element> * postNode(CTreeNode<Element> * node);  //后继节点
			
		public:
			CTreeNode<Element> *root;
	};

#endif


template<class Element>
CBinaryTree<Element>::CBinaryTree()   //构造函数,结点初始化为空
{
	root = NULL;
}

template<class Element>
CBinaryTree<Element>::~CBinaryTree()   
{
	root = NULL;
}

template<class Element>
bool CBinaryTree<Element>::treeEmpty()   //判断结点是否为空
{
	return root == NULL;
}

template<class Element>
bool CBinaryTree<Element>::insertElement(Element value)   //插入结点
{
	CTreeNode<Element> *p = root;          
	CTreeNode<Element> *q = NULL;      
	while(p != NULL)          
	{
		q = p;
		if (value < p->key)
			p = p->lchild;       //p初始化为root,当value小于p->key时,p = p->lchild
		else
			p = p->rchild;       //当value大于p->key时,p = p->rchild ,直到p为空
	}
	if (q == NULL)
	{
		root = new CTreeNode<Element>(value);    //当q为空,说明p为空,树也为空。新建一个根结点
		return true;
	}
	else if (value < q->key)          //当值小于q->key,把value放在q的左子树
	{
		q->lchild = new CTreeNode<Element>(value);
		return true;
	}
	else
	{
		q->rchild = new CTreeNode<Element>(value);
		return true;
	}
	return false;
}

template<class Element>
void CBinaryTree<Element>::inorderTree(CTreeNode<Element> *root)  //中序遍历,递归输出左子树和右子树即从小到大排列的
{
	if (root != NULL)
	{
		inorderTree(root->lchild);
		cout<<root->key<<endl;
		inorderTree(root->rchild);
	}
}

template<class Element>
CTreeNode<Element> * CBinaryTree<Element>::search(Element value)  //查找
{
	CTreeNode<Element> *p = root;
	while (p != NULL && p->key != value)
	{
		if (value < p->key)
			p = p->lchild;
		else
			p = p->rchild;
	}
	return p;
}

template<class Element>
CTreeNode<Element> * CBinaryTree<Element>::parent(CTreeNode<Element> * child)    
{
	CTreeNode<Element> *p = root;
	CTreeNode<Element> *q = NULL;
	while(p != NULL && p->key != child->key)     //从根遍历到child。其父节点就是q
	{
		q = p ;
		if (p->key>child->key)
		{
			p = p->lchild;
		}
		else
		{
			p = p->rchild;
		}
	}
	return q;
}

template<class Element>
CTreeNode<Element> * CBinaryTree<Element>::maxValue(CTreeNode<Element> *root)
{
	CTreeNode<Element> *p = root;
	while (p->rchild!=NULL)
	{
		p = p->rchild;            //一直向右遍历就可以得到最大值
	}
	return p;
}

template<class Element>
CTreeNode<Element> * CBinaryTree<Element>::minValue(CTreeNode<Element> *root)
{
	CTreeNode<Element> *p = root;
	while (p->lchild!=NULL)
	{
		p = p->lchild;          //一直想左遍历就可以得到最小值
	}
	return p;

}

template<class Element>
CTreeNode<Element> * CBinaryTree<Element>::postNode(CTreeNode<Element> * node)  //后继结点
{
	if (node->rchild != NULL)         //1.右子树不为空的时候为右子树的最小值
	{
		return minValue(node->rchild);
	}
	CTreeNode<Element> *p = node;
	CTreeNode<Element> *par = parent(p);
	while (par != NULL && par->rchild == p)        //2.当其父节点的左子树是它时才跳出循环。
	{
		p = par;
		par = parent(p);
	}
	return par;
}

template<class Element>
bool CBinaryTree<Element>::deleteValue(Element value)
{
	CTreeNode<Element> *p = search(value);     
	CTreeNode<Element> *q = NULL;
	CTreeNode<Element> *s = NULL;
	if (p->lchild == NULL || p->rchild == NULL)
	{
		q = p;
	}
	else
		q = postNode(p);

	s = parent(q);
	if (q->lchild != NULL)
	{
		if (s != NULL && s->lchild == q)
		{
			s->lchild = q->lchild;
		}
		else if (s!=NULL && s->rchild == q)
		{
			s->rchild = q->lchild;
		}
		else
		{
			if (s!=NULL && s->lchild == q )
			{
				s->lchild = q->rchild;
			}
			else if (s!=NULL && s->rchild == q)
			{
				s->rchild = q->rchild;
			}
		}
		if (s==NULL)
			root->key = q->key;
		
		if (q!=p)
		{
			p->key = q->key;
		}

		delete q;
		return true;
	}
}



测试:

#include <iostream>
#include "binaryTree.h"
#include "treeNode.h"

using namespace std;

int main()
{
	CBinaryTree<int> m_bTree;
    
    m_bTree.insertElement(15);
    m_bTree.insertElement(5);
    m_bTree.insertElement(3);

    m_bTree.insertElement(12);
    m_bTree.insertElement(13);
    m_bTree.insertElement(10);
    m_bTree.insertElement(6);
    m_bTree.insertElement(7);
    m_bTree.insertElement(16);
    m_bTree.insertElement(20);
    m_bTree.insertElement(18);
    m_bTree.insertElement(23);
    m_bTree.deleteValue(5);
    m_bTree.inorderTree(m_bTree.root);
	cout<<"最小值为:"<<m_bTree.minValue(m_bTree.root)->key<<endl;
	cout<<"最大值为:"<<m_bTree.maxValue(m_bTree.root)->key<<endl;

    system("pause");
    return 1;
}

结果:

《算法导论》学习笔记--第十二章 二叉查找树_第1张图片


另外,可以实现二叉树是否为平衡二叉树:

//检测二叉树是不是平衡二叉树
	int DepthTree(CTreeNode<Element> *root);//树的高度
	bool isBalanceTree(CTreeNode<Element> *root);//判断是否平衡

实现为:

template<class Element>
int CBinaryTree<Element>::DepthTree(CTreeNode<Element> *root)
{
	if (root == NULL)
	{
		return 0;
	}
	else
	{
		int leftLength = DepthTree(root->lchild);
		int rightLength = DepthTree(root->rchild);
		return 1+((leftLength>rightLength)?leftLength:rightLength);
	}
}

template<class Element>
bool CBinaryTree<Element>::isBalanceTree(CTreeNode<Element> *root)
{
	if (root == NULL)
	{
		return true;
	}
	int depthLeft = DepthTree(root->lchild);
	int depthRight = DepthTree(root->rchild);

	if (abs(depthLeft - depthRight) > 1)
	{
		return false;
	}
	else
		return isBalanceTree(root->lchild)&&isBalanceTree(root->rchild);
}


你可能感兴趣的:(数据结构,算法,null,delete,search,insert)