zoukankan      html  css  js  c++  java
  • 1

    1123. Is It a Complete AVL Tree (30)

    时间限制: 400 ms
    内存限制: 65536 kB
    代码长度限制: 16000 B
    判题程序:Standard

      An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Figures 1-4 illustrate the rotation rules.
    Now given a sequence of insertions, you are supposed to output the level-order traversal sequence of the resulting AVL tree, and to tell if it is a complete binary tree.

    Input   Each input file contains one test case. For each case, the first line contains a positive integer N (<= 20). Then N distinct integer keys are given in the next line. All the numbers in a line are separated by a space.
    Output   For each test case, insert the keys one by one into an initially empty AVL tree. Then first print in a line the level-order traversal sequence of the resulting AVL tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line. Then in the next line, print "YES" if the tree is complete, or "NO" if not.
    Examples
    >| Input| | ------------- | | 5
    88 70 61 63 65 | | Output | | 70 63 88 61 65
    YES |
    >| ------------- | >| Input| | 8
    88 70 61 96 120 90 65 68| | Output | | 88 65 96 61 70 90 120 68
    NO|   Notes   
    作者   CHEN, Yue

      下面程序的AVL树是用平衡因子实现的,平衡处理是独立的,再插入操作完成后进行,这样的写法可能更清晰,易于理解。
      判断树是否为完全二叉树的做法是,用一个存储节点指针的queue对树进行层次遍历,从根节点开始,先将其指针加入queue,不断将queue的队首元素的左右节点指针(空指针也加入)加入queue后将队首元素移出,直到queue空为止。在遍历的过程中,queue队首元素第一次为空指针时,如果已经将所有节点遍历完(计数即可),就说明该树为完全二叉树。
      

    #include <iostream>
    #include <algorithm>
    #include <map>
    #include <vector>
    #include <functional>
    #include <string>
    #include <cstring>
    #include <queue>
    #include <set>
    #include <stack>
    #include <cmath>
    #include <cstdio>
    #include <sstream>
    #include <iomanip>
    using namespace std;
    #define IOS ios_base::sync_with_stdio(false)
    #define TIE std::cin.tie(0)
    #define MIN2(a,b) (a<b?a:b)
    #define MIN3(a,b) (a<b?(a<c?a:c):(b<c?b:c))
    #define MAX2(a,b) (a>b?a:b)
    #define MAX3(a,b,c)  (a>b?(a>c?a:c):(b>c?b:c))
    typedef long long LL;
    typedef unsigned long long ULL;
    const int INF = 0x3f3f3f3f;
    const double PI = 4.0*atan(1.0);
    const double eps = 1e-6;
    
    int n, x;
    
    struct AVLTree{
    	struct AVLTreeNode{
    		int data;
    		int balanceFactor;//平衡因子
    		AVLTreeNode * left = NULL;
    		AVLTreeNode * right = NULL;
    		AVLTreeNode(){}
    		AVLTreeNode(int item) :data(item){}
    	};
    	typedef AVLTreeNode * AVLTreeNodePointer;
    	void insert(int item);
    	void adj();
    	int adjAux(AVLTreeNodePointer & subtreeRoot, int h);
    	void leftSingleRotation(AVLTreeNodePointer & subtreeRoot);
    	void rightSingleRotation(AVLTreeNodePointer & subtreeRoot);
    	void leftDoubleRotation(AVLTreeNodePointer & subtreeRoot);
    	void rightDoubleRotation(AVLTreeNodePointer & subtreeRoot);
    	void levelorder(AVLTreeNodePointer subtreeRoot) const;
    	AVLTreeNodePointer myRoot = NULL;
    };
    
    void AVLTree::insert(int item)
    {
    	AVLTreeNodePointer locptr = myRoot;				 //查找指针
    	AVLTreeNodePointer parent = 0;
    	bool found = false;						 //表示item是否已存在于树中
    	while (!found && locptr != 0)
    	{
    		parent = locptr;
    		if (item < locptr->data)             //下降到左子树
    			locptr = locptr->left;
    		else if (locptr->data < item)        //下降到右子树
    			locptr = locptr->right;
    		else
    			found = true;                    //item被找到
    	}
    	if (!found)								 //item未被找到
    	{
    		//创建包含item的节点
    		locptr = new AVLTreeNode(item);
    		if (parent == 0)					 //当前树为空
    			myRoot = locptr;
    		else if (item < parent->data)        //作为父亲节点的左孩子插入
    			parent->left = locptr;
    		else
    			parent->right = locptr;          //作为父亲节点的右孩子插入
    	}
    	else
    		;//item已存在 
    }
    
    void AVLTree::adj()
    {
    	adjAux(myRoot, 1);
    }
    
    int AVLTree::adjAux(AVLTreeNodePointer & subtreeRoot, int h)
    {
    	//参数height为节点的高度,设定根节点的高度为1,自顶向下逐层的高度依次加1
    	int leftHeight = 0, rightHeight = 0;
    	if (subtreeRoot != NULL)
    	{
    		h++;                                                 //高度增加1
    		leftHeight = adjAux(subtreeRoot->left, h);    //左子树相对根节点的高度
    		rightHeight = adjAux(subtreeRoot->right, h);  //右子树相对根节点的高度
    		subtreeRoot->balanceFactor = leftHeight - rightHeight;    //计算平衡因子
    
    		if (subtreeRoot->balanceFactor == 2)                      //左子树高
    		{
    			if (subtreeRoot->left->balanceFactor == 1)            //右单旋
    				rightSingleRotation(subtreeRoot);
    			else if (subtreeRoot->left->balanceFactor == -1)      //右双旋
    				rightDoubleRotation(subtreeRoot);
    			return adjAux(subtreeRoot, h - 1);        //旋转调整后重新计算平衡因子
    		}
    		else if (subtreeRoot->balanceFactor == -2)				  //右子树高
    		{
    			if (subtreeRoot->right->balanceFactor == -1)          //左单旋
    				leftSingleRotation(subtreeRoot);
    			else if (subtreeRoot->right->balanceFactor == 1)      //左双旋
    				leftDoubleRotation(subtreeRoot);
    			return adjAux(subtreeRoot, h - 1);		  //旋转调整后重新计算平衡因子
    		}
    		else                                                      //不需调整,返回左子树和右子树树高的最大值
    		{                                                         //即为父亲节点的高度
    			return max(leftHeight, rightHeight);
    		}
    	}
    	else
    		return h;                                             //节点为空
    }
    
    void AVLTree::leftSingleRotation(AVLTreeNodePointer & subtreeRoot)
    {
    	AVLTreeNodePointer rightTree = subtreeRoot->right;
    	subtreeRoot->right = rightTree->left;
    	rightTree->left = subtreeRoot;
    	subtreeRoot = rightTree;
    }
    
    void AVLTree::rightSingleRotation(AVLTreeNodePointer & subtreeRoot)
    {
    	AVLTreeNodePointer leftTree = subtreeRoot->left;
    	subtreeRoot->left = leftTree->right;
    	leftTree->right = subtreeRoot;
    	subtreeRoot = leftTree;
    }
    
    void AVLTree::leftDoubleRotation(AVLTreeNodePointer & subtreeRoot)
    {
    	AVLTreeNodePointer rightTree = subtreeRoot->right,
    		child = rightTree->left;
    
    	//右旋
    	rightTree->left = child->right;
    	child->right = rightTree;
    	subtreeRoot->right = child;
    
    	//左旋
    	subtreeRoot->right = child->left;
    	child->left = subtreeRoot;
    	subtreeRoot = child;
    }
    
    void AVLTree::rightDoubleRotation(AVLTreeNodePointer & subtreeRoot)
    {
    	AVLTreeNodePointer leftTree = subtreeRoot->left,
    		child = leftTree->right;
    
    	//左旋
    	leftTree->right = child->left;
    	child->left = leftTree;
    	subtreeRoot->left = child;
    
    	//右旋
    	subtreeRoot->left = child->right;
    	child->right = subtreeRoot;
    	subtreeRoot = child;
    }
    
    void AVLTree::levelorder(AVLTreeNodePointer subtreeRoot) const
    {
    	queue<AVLTreeNodePointer> que;
    	que.push(myRoot);
    	bool first = true, nullfir=true;
    	bool cmp = false;
    	int cnt = 0;
    	while (!que.empty()){
    		AVLTreeNodePointer ptr = que.front();
    		que.pop();
    		if (ptr == NULL){
    			if (nullfir){
    				nullfir = false;
    				if (cnt == n)
    					cmp = true;
    			}
    			continue;
    		}
    		cnt++;
    		if(first) first = false;
    		else printf(" ");
    		printf("%d", ptr->data);
    		que.push(ptr->left);
    		que.push(ptr->right);
    	}
    	printf("
    %s
    ", cmp ? "YES" : "NO");
    }
    
    int main()
    {
    	AVLTree tree;
    	scanf("%d", &n);
    	for (int i = 0; i < n; i++)
    	{
    		scanf("%d", &x);
    		tree.insert(x);
    		tree.adj();
    	}
    	tree.levelorder(tree.myRoot);
    	//system("pause");
    }
    //system("pause");
    
  • 相关阅读:
    github入门到上传本地项目
    17-索引
    16-pymysql模块的使用
    15-可视化工具Navicat的使用
    C语言/C++知识
    Apk反编译那些事
    CTF基本常识
    WebView net::ERR_CLEARTEXT_NOT_PERMITTED&&net::ERR_INTERNET_DISCONNECTED
    测试
    zookeeper-3.4.5安装&3台机器安装之后 ./zkServer.sh status 之后会显示“Error contacting service. It is probably not running.”的解决办法
  • 原文地址:https://www.cnblogs.com/cumulonimbus/p/6495620.html
Copyright © 2011-2022 走看看