DSW算法(《C++数据结构与算法》P200)

1 构建思路

先将任意的二叉查找树转化为类似于链表的树,使之成为主链或者主干;然后进行适当的旋转。

2 旋转

3 代码


#include <iostream>

#include<math.h>
#include<stdlib.h>
#include<list>
#include<stack>
#include<queue>
using namespace std;

//栈实现
template<class T>
class Stack : public stack<T> 
{
public:
	T pop() 
	{
		T tmp = stack<T>::top();
		stack<T>::pop();
		return tmp;
	}
};

//队列实现
template<class T>
class Queue : public queue<T> 
{
public:
	T dequeue() 
	{
		T tmp = queue<T>::front();
		queue<T>::pop();
		return tmp;
	}

	void enqueue(const T& el) 
	{
		queue<T>::push(el);
	}
};

//树节点类
template<class T>
class Node 
{
public:
	Node() :left(NULL), right(NULL) {}
	Node(const T& e, Node<T>* l = NULL, Node<T>*r = NULL) :data(e), left(l), right(r) {}
	~Node() {}
	T data;
	Node* left;
	Node* right;
};

//二叉查找树的实现类
template<class T>
class BST 
{
public:
	BST() :root(NULL), count(0) {}
	BST(T* a, int len);	//根据数组中的数据构造树,调试测试用
	~BST() 
	{
		clear();
	}

	bool isEmpty() const 
	{
		return NULL == root;
	}

	void clear() 
	{
		clear(root);
		root = NULL;
	}

	unsigned int count;
	void insert(const T&);		//插入
	void inorder() 
	{//深度遍历之中序树遍历
		inorder(root);
	}

	void breadthFirst();		//广度优先遍历
	virtual void visit(Node<T>* p) 
	{
		cout << p->data << ' ';
	}

protected:
	Node<T>* root; //根节点
	void clear(Node<T>*);
	void inorder(Node<T>*);
};

//根据数组中的内容构造树
template<class T>
BST<T>::BST(T* a, int len) 
{
	root = NULL;
	count = 0;
	for (int i = 0; i < len; i++) 
	{
		insert(a[i]);
	}
}

//清除节点p及其子节点
template<class T>
void BST<T>::clear(Node<T> *p) 
{
	if (p != NULL) 
	{
		clear(p->left);
		clear(p->right);
		delete p;
	}

	count = 0;
}

//插入,非递归形式
template<class T>
void BST<T>::insert(const T& el) 
{
	Node<T> *p = root, *prev = NULL;
	while (p != NULL) 
	{  // find a place for inserting new node;
		prev = p;
		if (el < p->data)
			p = p->left;
		else p = p->right;
	}

	if (root == NULL)    // tree is empty;
		root = new Node<T>(el);
	else if (el < prev->data)
		prev->left = new Node<T>(el);
	else prev->right = new Node<T>(el);

	++count;
}

//广度优先遍历(从上到下,从左到右,一层一层的向下访问)
template<class T>
void BST<T>::breadthFirst() 
{
	Queue<Node<T>*> m_queue;	//要理解这里为什么要用队列,这个队列的作用是把下一层的数据放到本层数据的后面
	Node<T>* p = root;
	if (p != NULL) 
	{
		m_queue.enqueue(p);
		while (!m_queue.empty()) 
		{
			p = m_queue.dequeue();
			visit(p);
			if (p->left != NULL)
				m_queue.enqueue(p->left);
			if (p->right != NULL)
				m_queue.enqueue(p->right);
		}
	}
}

//中序遍历,递归实现
template<class T>
void BST<T>::inorder(Node<T> *p) 
{
	if (p != NULL) 
	{
		inorder(p->left);
		visit(p);
		inorder(p->right);
	}
}

template<class T>
class DswBST : public BST<T> 
{
public:
	DswBST(T* a, int len);    //根据数组中的数据构造树,调试测试用
	void dswBalance();
protected:
	void createBackbone();
	void creatPerfectTree();
	void rotateRight(Node<T>* Gr, Node<T>* Par, Node<T>* Ch);
	void rotateLeft(Node<T>* Gr, Node<T>* Par, Node<T>* Ch);
};

template<class T>
DswBST<T>::DswBST(T* a, int len) 
{
	for (int i = 0; i < len; i++) 
	{
		this->insert(a[i]);
	}
}

template<class T>
void DswBST<T>::dswBalance() 
{
	createBackbone();
	creatPerfectTree();
}

// 二叉查找树转化成主链的过程分析
/**********************************************************************************************
*  5 <-tmp    5                5               5                   5
*   \               \                 \               \                    \
*    10             10              10              10                10
*      \               \                  \               \                    \
*       20            15               15              15                 15
*      /  \               \                 \               \                    \
*     15  30            20              20              20                 20
*          / \               \                  \                \                  \
*        25 40            30 <-tmp       25 <-tmp  23                23
*       /  \                 /  \                /  \               \                 \
*     23    28          25   40           23   30           25               25
*                         /  \                        /  \              \                 \
*                       23   28                  28   40            30 <-tmp    28
*                                                                          / \                \
*                                                                        28 40             30
*                                                                                               \
*                                                                                               40<-tmp
***********************************************************************************************/
template<class T>
void DswBST<T>::createBackbone() 
{
	Node<T> *Gr = 0, *Par = this->root, *Ch = 0;
	while (Par != 0) 
	{
		Ch = Par->left;
		if (Ch != 0) 
		{
			rotateRight(Gr, Par, Ch);
			Par = Ch;
		}
		else 
		{
			Gr = Par;
			Par = Par->right;
		}
		// 旋转过程中,如果是绕根节点的右节点旋转时要将根节点置为原根节点的右节点
		if (Gr == 0)
			this->root = Ch;
	}
}

/************************************************************************
 *  子节点Ch围绕父节点Par的右旋转
 *   Before      After
 *    Gr          Gr
 *     \           \
 *     Par         Ch
 *    /  \        /  \
 *   Ch   Z      X   Par
 *  /  \            /  \
 * X    Y          Y    Z
 ***********************************************************************/
template<class T>
void DswBST<T>::rotateRight(Node<T>* Gr, Node<T>* Par, Node<T>* Ch) 
{
	if (Gr != 0)
		Gr->right = Ch;
	Par->left = Ch->right;
	Ch->right = Par;
}

template<class T>
void DswBST<T>::rotateLeft(Node<T>* Gr, Node<T>* Par, Node<T>* Ch) 
{
	if (Gr != 0)
		Gr->right = Ch;
	Par->right = Ch->left;
	Ch->left = Par;
}

template<class T>
void DswBST<T>::creatPerfectTree() 
{
	int n = this->count;
	if (n < 3) 
	{
		return; //节点数目小于3不用平衡
	}

	int m = (1 << ((int)(log10(n + 1) / log10(2)))) - 1;
	Node<T> *Gr = 0;
	Node<T> *Par = this->root;
	Node<T> *Ch = this->root->right;

	this->root = this->root->right; //修改root指针
	// 第一阶段: 左旋n-m次
	for (int i = 0; i < n - m; i++) 
	{
		rotateLeft(Gr, Par, Ch);
		Gr = Ch;
		Par = Gr->right;
		if (0 != Par) 
		{
			Ch = Par->right;
		}
		else 
		{
			break;
		}
	}

	// 第二阶段,进入while循环
	while (m > 1) 
	{
		m = m >> 1;
		Node<T> *Gr = 0;
		Node<T> *Par = this->root;
		Node<T> *Ch = this->root->right;

		this->root = this->root->right;
		for (int i = 0; i < m; i++) 
		{
			rotateLeft(Gr, Par, Ch);
			Gr = Ch;
			Par = Gr->right;
			if (0 != Par) 
			{
				Ch = Par->right;
			}
			else 
			{
				break;
			}
		}
	}
}
int main()
{
	int a[] = { 5,10,20,15,30,25,40,23,28 };
	DswBST<int> tree(a, sizeof(a) / sizeof(a[0]));
	tree.breadthFirst();
	cout << endl;
	tree.inorder();
	cout << endl;

	tree.dswBalance();
	tree.breadthFirst();
	cout << endl;
	tree.inorder();

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值