数据结构之平衡二叉树的非递归实现

平衡二叉树

  平衡二叉树因插入和删除时都要从插入和删除的位置向上到根节点判断是否平衡的特点,用递归比较容易实现。但是利用循环同样可以实现对二叉树的平衡操作 只是相应的有些麻烦。

以下是一些结构和宏的定义

#pragma once

#define NAME_SIZE 20
#define BUFFER_SIZE 30

#define INIT_STACK_SIZE 100
#define INCREASE_SIZE 50

#define QUEUE_INIT_SIZE 100

typedef struct {
	wchar_t szHeroName[NAME_SIZE];
	int iGoldPrice;
}ITEM;

typedef struct node {
	ITEM item;
	struct node * pParent;
	struct node * pLeft;
	struct node * pRight;
	int iHeight;
}NODE;

typedef NODE * TREE;

typedef struct {
	NODE ** pBase;
	NODE ** pTop;
	int iMaxSize;
}STACK;

typedef struct {
	NODE ** pBase;
	int iFront, iRear;
	int iItem;
}QUEUE;

平衡二叉树遍历的时候可以先序、中序、后序还可以按层遍历,需要借助栈和队列,以下是栈和队列的实现

bool QueueIsEmpty(const QUEUE * pq)
{
	return pq->iItem == 0;
}

bool QueueIsFull(const QUEUE * pq)
{
	return pq->iItem == QUEUE_INIT_SIZE;
}

int QueueItemCount(const QUEUE * pq)
{
	return pq->iItem;
}

bool InitQueue(QUEUE * pq)
{
	if (!(pq->pBase = (NODE **)malloc(sizeof(NODE *)*QUEUE_INIT_SIZE)))
		return false;
	pq->iFront = pq->iRear = 0;
	pq->iItem = 0;
	return true;
}

bool EnQueue(NODE * pn, QUEUE * pq)
{
	if (QueueIsFull(pq))
		return false;
	pq->pBase[pq->iRear] = pn;
	pq->iRear = (pq->iRear + 1) % QUEUE_INIT_SIZE;
	pq->iItem++;
	return true;
}

bool DeQueue(NODE ** ppn, QUEUE * pq)
{
	if (QueueIsEmpty(pq))
		return false;
	*ppn = pq->pBase[pq->iFront];
	pq->iFront = (pq->iFront + 1) % QUEUE_INIT_SIZE;
	pq->iItem--;
	return true;
}

void DestroyQueue(QUEUE * pq)
{
	free(pq->pBase);
	pq->pBase = NULL;
	pq->iFront = pq->iRear = pq->iItem = 0;
}
/**************************************************************************************/
bool InitStack(STACK * ps)
{
	if (!(ps->pBase = (NODE **)malloc(sizeof(NODE *)*INIT_STACK_SIZE)))
		return false;
	ps->pTop = ps->pBase;
	ps->iMaxSize = INIT_STACK_SIZE;
	return true;
}

bool StackIsEmpty(STACK * ps)
{
	return ps->pTop == ps->pBase;
}

bool StackIsFull(STACK * ps)
{
	return (ps->pTop - ps->pBase) == ps->iMaxSize;
}

bool PushStack(STACK * ps, NODE * pn)
{
	NODE ** ppNew;

	if (StackIsFull(ps))
	{
		if (!(ppNew = (NODE **)realloc(ps->pTop, (ps->iMaxSize + INCREASE_SIZE)*sizeof(NODE *))))
			return false;
		ps->pBase = ppNew;
		ps->pTop = ps->pBase + ps->iMaxSize;
		ps->iMaxSize += INCREASE_SIZE;
	}
	*(ps->pTop++) = pn;

	return true;
}

bool PopStack(STACK * ps, NODE ** ppn)
{
	if (StackIsEmpty(ps))
		return false;
	*ppn = *(--ps->pTop);
	return true;
}

bool GetTop(STACK * ps, NODE ** ppn)
{
	if (StackIsEmpty(ps))
		return false;
	*ppn = *(ps->pTop - 1);
	return true;
}

void DestroyStack(STACK * ps)
{
	free(ps->pBase);
	ps->pBase = ps->pTop = NULL;
	ps->iMaxSize = 0;
}

  有了上面的函数可以来实现平衡二叉树的非递归算法   为了做到可以从插入或删除结点的位置一直到根节点来判断是否平衡,在结点的定义中比递归算法时多了一个被定义为pParent 的指向父节点的指针 有了这个指针我们就可以实现二叉树的平衡操作,平衡工作的核心在BalanceTree()函数中,删除结点的方法和上一篇递归算法一样。

void InitTree(TREE * pTree)
{
	*pTree = NULL;
}

int GetHeight(NODE * pRoot)
{
	if (pRoot)
		return pRoot->iHeight;
	else
		return 0;
}

int GetBL(NODE * pRoot)
{
	if (pRoot)
		return GetHeight(pRoot->pLeft) - GetHeight(pRoot->pRight);
	else
		return 0;
}

NODE * Retate_LL(NODE * pRoot)
{
	NODE * pNode;

	pNode = pRoot->pLeft;

	pNode->pParent = pRoot->pParent;
	pRoot->pParent = pNode;

	pRoot->pLeft = pNode->pRight;
	if (pNode->pRight != NULL)
		pNode->pRight->pParent = pRoot;
	pNode->pRight = pRoot;

	pRoot->iHeight = max(GetHeight(pRoot->pLeft), GetHeight(pRoot->pRight)) + 1;
	pNode->iHeight = max(GetHeight(pNode->pLeft), GetHeight(pNode->pRight)) + 1;

	return pNode;
}


NODE * Retate_RR(NODE * pRoot)
{
	NODE * pNode;

	pNode = pRoot->pRight;

	pNode->pParent = pRoot->pParent;
	pRoot->pParent = pNode;

	pRoot->pRight = pNode->pLeft;
	if (pNode->pLeft != NULL)
		pNode->pLeft->pParent = pRoot;
	pNode->pLeft = pRoot;

	pRoot->iHeight = max(GetHeight(pRoot->pLeft), GetHeight(pRoot->pRight)) + 1;
	pNode->iHeight = max(GetHeight(pNode->pLeft), GetHeight(pNode->pRight)) + 1;

	return pNode;
}

NODE * Retate_LR(NODE * pRoot)
{
	pRoot->pLeft = Retate_RR(pRoot->pLeft);
	return Retate_LL(pRoot);
}

NODE * Retate_RL(NODE * pRoot)
{
	pRoot->pRight = Retate_LL(pRoot->pRight);
	return Retate_RR(pRoot);
}

NODE * BalanceTree(NODE * pRoot, NODE * pNode)
{
	bool B_IsRoot = false;
	NODE * pParent;

	while (pNode != NULL)
	{
		if (pNode == pRoot) B_IsRoot = true;

		pParent = pNode->pParent;
		pNode->iHeight = max(GetHeight(pNode->pLeft), GetHeight(pNode->pRight)) + 1;

		if (GetBL(pNode) == 2)
		{
			if (GetBL(pNode->pLeft) >= 0)
			{
				if (pNode == pRoot)
					pRoot = Retate_LL(pNode);
				else if (pNode == pParent->pLeft)
					pParent->pLeft = Retate_LL(pNode);
				else
					pParent->pRight = Retate_LL(pNode);
			}
			else
			{
				if (pNode == pRoot)
					pRoot = Retate_LR(pNode);
				else if (pNode == pParent->pLeft)
					pParent->pLeft = Retate_LR(pNode);
				else
					pParent->pRight = Retate_LR(pNode);
			}
		}
		else if (GetBL(pNode) == -2)
		{
			if (GetBL(pNode->pRight) <= 0)
			{
				if (pNode == pRoot)
					pRoot = Retate_RR(pNode);
				else if (pNode == pParent->pLeft)
					pParent->pLeft = Retate_RR(pNode);
				else
					pParent->pRight = Retate_RR(pNode);
			}
			else
			{
				if (pNode == pRoot)
					pRoot = Retate_RL(pNode);
				else if (pNode == pParent->pLeft)
					pParent->pLeft = Retate_RL(pNode);
				else
					pParent->pRight = Retate_RL(pNode);
			}
		}
		if (B_IsRoot) break;
		pNode = pParent;
	}
	return pRoot;
}

NODE * SearchItem(NODE * pRoot, const ITEM * pItem)
{
	int iCmp;
	NODE * pNode;

	pNode = pRoot;

	while (pNode != NULL)
	{
		iCmp = lstrcmp(pNode->item.szHeroName, pItem->szHeroName);
		if (iCmp > 0)
			pNode = pNode->pLeft;
		else if (iCmp < 0)
			pNode = pNode->pRight;
		else
			break;
	}
	return pNode;
}

NODE * MakeNode(ITEM * pItem)
{
	NODE * pNew;

	pNew = (NODE *)malloc(sizeof(NODE));
	pNew->item = *pItem;
	pNew->iHeight = 1;
	pNew->pLeft = pNew->pRight = NULL;
	pNew->pParent = NULL;

	return pNew;
}

NODE * InsertItem(NODE * pRoot, ITEM * pItem)
{
	NODE * pNew;
	NODE * pNode;
	NODE * pParent;

	pNew = MakeNode(pItem);

	pParent = NULL;

	if (pRoot == NULL) return pNew;

	pNode = pRoot;
	while (pNode != NULL)
	{
		pParent = pNode;
		if (lstrcmp(pNode->item.szHeroName, pItem->szHeroName) > 0)
			pNode = pNode->pLeft;
		else
			pNode = pNode->pRight;
	}
	if (lstrcmp(pParent->item.szHeroName, pItem->szHeroName) > 0)
		pParent->pLeft = pNew;
	else
		pParent->pRight = pNew;
	pNew->pParent = pParent;

	pRoot = BalanceTree(pRoot, pParent);

	return pRoot;
}

NODE * DeleteNode(NODE * pRoot, NODE * pNode)
{
	NODE * pParent;
	NODE * pMaxNode;

	if (pRoot == NULL) return pRoot;

	while (pNode->pLeft != NULL)
	{
		pMaxNode = pNode->pLeft;
		while (pMaxNode->pRight != NULL)
			pMaxNode = pMaxNode->pRight;
		pNode->item = pMaxNode->item;
		pNode = pMaxNode;
	}

	if (pNode == pRoot)
	{
		pParent = NULL;
		if (pNode->pRight != NULL)
			pNode->pRight->pParent = pNode->pParent;
		pRoot = pNode->pRight;
		free(pNode);
	}
	else
	{
		pParent = pNode->pParent;
		if (pParent->pLeft == pNode)
			pParent->pLeft = pNode->pRight;
		else
			pParent->pRight = pNode->pRight;
		if (pNode->pRight != NULL)
			pNode->pRight->pParent = pParent;
		free(pNode);
	}
	pRoot = BalanceTree(pRoot, pParent);

	return pRoot;
}

NODE * DeleteItem(NODE * pRoot, ITEM * pItem)
{
	return DeleteNode(pRoot, SearchItem(pRoot, pItem));
}

void VisitItem(NODE * pNode)
{
	_tprintf(L"%ls", pNode->item.szHeroName);
	_tprintf(L"  %d$\n", pNode->item.iGoldPrice);
}

void PreOrder(NODE * pRoot)
{
	NODE * pNode;
	STACK Stack_pNode;

	InitStack(&Stack_pNode);
	pNode = pRoot;

	while (pNode != NULL || !StackIsEmpty(&Stack_pNode))
	{
		if (pNode != NULL)
		{
			VisitItem(pNode);
			PushStack(&Stack_pNode, pNode);
			pNode = pNode->pLeft;
		}
		else
		{
			PopStack(&Stack_pNode, &pNode);
			pNode = pNode->pRight;
		}
	}
	DestroyStack(&Stack_pNode);
}

void InOrder(NODE * pRoot)
{
	NODE * pNode;
	STACK Stack_pNode;

	InitStack(&Stack_pNode);
	pNode = pRoot;

	while (pNode != NULL || !StackIsEmpty(&Stack_pNode))
	{
		if (pNode != NULL)
		{
			PushStack(&Stack_pNode, pNode);
			pNode = pNode->pLeft;
		}
		else
		{
			PopStack(&Stack_pNode, &pNode);
			VisitItem(pNode);
			pNode = pNode->pRight;
		}
	}
	DestroyStack(&Stack_pNode);
}

void PostOrder(NODE * pRoot)
{
	NODE * pNode;
	NODE * pPreNode;
	STACK Stack_pNode;

	InitStack(&Stack_pNode);
	pNode = pRoot;
	pPreNode = NULL;

	while (pNode != NULL || !StackIsEmpty(&Stack_pNode))
	{
		if (pNode != NULL)
		{
			PushStack(&Stack_pNode, pNode);
			pNode = pNode->pLeft;
		}
		else
		{
			GetTop(&Stack_pNode, &pNode);
			if (pNode->pRight == NULL || pNode->pRight == pPreNode)
			{
				VisitItem(pNode);
				pPreNode = pNode;
				PopStack(&Stack_pNode, &pNode);
				pNode = NULL;
			}
			else
				pNode = pNode->pRight;
		}
	}
	DestroyStack(&Stack_pNode);
}

bool LevelCheck(NODE * pRoot)
{
	if (pRoot == NULL)
		return true;

	int iLevel;
	NODE * pNode = NULL;
	QUEUE Queue_pNode;

	InitQueue(&Queue_pNode);
	EnQueue(pRoot, &Queue_pNode);

	while (!QueueIsEmpty(&Queue_pNode))
	{
		iLevel = Queue_pNode.iRear;
		while (Queue_pNode.iFront != iLevel)
		{
			DeQueue(&pNode, &Queue_pNode);
			VisitItem(pNode);
			if (pNode->pLeft)
				EnQueue(pNode->pLeft, &Queue_pNode);
			if (pNode->pRight)
				EnQueue(pNode->pRight, &Queue_pNode);
		}
		putchar('\n');
	}
	DestroyQueue(&Queue_pNode);
	return true;
}

int CheckHeight(NODE * pRoot)
{
	if (pRoot == NULL)
		return 0;

	int iHeight = 0;
	int iLevelNodeCnt;
	NODE * pNode = NULL;
	QUEUE Queue_pNode;

	InitQueue(&Queue_pNode);
	EnQueue(pRoot, &Queue_pNode);

	while (!QueueIsEmpty(&Queue_pNode))
	{
		iLevelNodeCnt = Queue_pNode.iRear;
		while (Queue_pNode.iFront != iLevelNodeCnt)
		{
			DeQueue(&pNode, &Queue_pNode);
			if (pNode->pLeft)
				EnQueue(pNode->pLeft, &Queue_pNode);
			if (pNode->pRight)
				EnQueue(pNode->pRight, &Queue_pNode);
		}
		iHeight++;
	}
	return iHeight;
}

bool CheckAVL(NODE * pRoot)
{
	int a;
	STACK Stack_pNode;
	NODE * pNode;

	InitStack(&Stack_pNode);
	pNode = pRoot;

	while (pNode != NULL || !StackIsEmpty(&Stack_pNode))
	{
		if (pNode != NULL)
		{
			PushStack(&Stack_pNode, pNode);
			pNode = pNode->pLeft;
		}
		else
		{
			PopStack(&Stack_pNode, &pNode);
			if (pNode->iHeight != (a = CheckHeight(pNode)))
				return false;
			if (abs(GetBL(pNode)) >= 2)
				return false;
			pNode = pNode->pRight;
		}
	}
	return true;
}

以上函数在控制台经过测试,以下是平衡二叉树的按层遍历和平衡二叉树的平衡测试结果。平衡测试通过调用CheckAVL()返回true来显示”成功”

	LevelCheck(Tree);

	if (CheckAVL(Tree))
		puts("成功");

《数据结构之平衡二叉树的非递归实现》

《数据结构之平衡二叉树的非递归实现》

平台:windows10 vs2015 完整工程代码:
http://download.csdn.net/detail/biqigu/9703772

    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/biqigu/article/details/53471323
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞