Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ AVL树-按位置打印值的最有效方法。C++;_C++_Algorithm_Avl Tree - Fatal编程技术网

C++ AVL树-按位置打印值的最有效方法。C++;

C++ AVL树-按位置打印值的最有效方法。C++;,c++,algorithm,avl-tree,C++,Algorithm,Avl Tree,嘿,我必须找到最有效的方法来打印一个数字,通过发布这个帖子。输入如下: 8 (N-> N Numbers) INS 100 (Add 100 to the tree) INS 200 (Add 200 to the tree) INS 300 (Add 300 to the tree) REM 200 (Remove the number 200 from the tree) PER 1 (Have to output the biggest number in the tree->

嘿,我必须找到最有效的方法来打印一个数字,通过发布这个帖子。输入如下:

8 (N-> N Numbers)
INS 100 (Add 100 to the tree)
INS 200 (Add 200 to the tree)
INS 300 (Add 300 to the tree)
REM 200 (Remove the number 200 from the tree)
PER 1 (Have to output the biggest number in the tree-> Shoud print 300)
INS 1000 (Add 1000 to the tree)
PER 1 ((Have to output the biggest number in the tree-> Shoud print 1000))
PER 2 (I have to output the second biggest number so:  300)
    y                   x
   / \                 / \
  x   D               A   y
 / \         ==>         / \
A   T2                  T2  D
   / \                 / \
  B   C               B   C
size of x:      from a+b+c+2       to     a+b+c+d+3
size of y:      from a+b+c+d+3     to     b+c+d+2
size of T2:     unchanged
我有一种这样打印的方法,但是速度非常慢,我必须维护一个O(N*log(N))

这是我的全部代码

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;

// An AVL tree node
struct node
{
    int key;
    struct node *left;
    struct node *right;
    int height;
};
// A utility function to get maximum of two integers
int max(int a, int b);
// A utility function to get height of the tree
int height(struct node *N)
{
    if (N == NULL)
            return 0;
    return N->height;
}
// A utility function to get maximum of two integers
int max(int a, int b)
{
    return (a > b)? a : b;
}
/* Helper function that allocates a new node with the given key and
    NULL left and right pointers. */
struct node* newNode(int key)
{
    struct node* node = (struct node*)
                                            malloc(sizeof(struct node));
    node->key   = key;
    node->left   = NULL;
    node->right  = NULL;
    node->height = 1;  // new node is initially added at leaf
    return(node);
}
// A utility function to right rotate subtree rooted with y
// See the diagram given above.
struct node *rightRotate(struct node *y)
{
    struct node *x = y->left;
    struct node *T2 = x->right;
    // Perform rotation
    x->right = y;
    y->left = T2;
    // Update heights
    y->height = max(height(y->left), height(y->right))+1;
    x->height = max(height(x->left), height(x->right))+1;
    // Return new root
    return x;
}
// A utility function to left rotate subtree rooted with x
// See the diagram given above.
struct node *leftRotate(struct node *x)
{
    struct node *y = x->right;
    struct node *T2 = y->left;
    // Perform rotation
    y->left = x;
    x->right = T2;
    //  Update heights
    x->height = max(height(x->left), height(x->right))+1;
    y->height = max(height(y->left), height(y->right))+1;
    // Return new root
    return y;
}
// Get Balance factor of node N
int getBalance(struct node *N)
{
    if (N == NULL)
            return 0;
    return height(N->left) - height(N->right);
}
struct node* insert(struct node* node, int key)
{
    /* 1.  Perform the normal BST rotation */
    if (node == NULL)
            return(newNode(key));
    if (key < node->key)
            node->left  = insert(node->left, key);
    else
            node->right = insert(node->right, key);
    /* 2. Update height of this ancestor node */
    node->height = max(height(node->left), height(node->right)) + 1;
    /* 3. Get the balance factor of this ancestor node to check whether
           this node became unbalanced */
    int balance = getBalance(node);
    // If this node becomes unbalanced, then there are 4 cases
    // Left Left Case
    if (balance > 1 && key < node->left->key)
            return rightRotate(node);
    // Right Right Case
    if (balance < -1 && key > node->right->key)
            return leftRotate(node);
    // Left Right Case
    if (balance > 1 && key > node->left->key)
    {
            node->left =  leftRotate(node->left);
            return rightRotate(node);
    }
    // Right Left Case
    if (balance < -1 && key < node->right->key)
    {
            node->right = rightRotate(node->right);
            return leftRotate(node);
    }
    /* return the (unchanged) node pointer */
    return node;
}
/* Given a non-empty binary search tree, return the node with minimum
   key value found in that tree. Note that the entire tree does not
   need to be searched. */
struct node * minValueNode(struct node* node)
{
    struct node* current = node;
    /* loop down to find the leftmost leaf */
    while (current->left != NULL)
            current = current->left;
    return current;
}
struct node* apagaNode(struct node* root, int key)
{
    // STEP 1: PERFORM STANDARD BST DELETE
    if (root == NULL)
            return root;
    // If the key to be deleted is smaller than the root's key,
    // then it lies in left subtree
    if ( key < root->key )
            root->left = apagaNode(root->left, key);
    // If the key to be deleted is greater than the root's key,
    // then it lies in right subtree
    else if( key > root->key )
            root->right = apagaNode(root->right, key);
    // if key is same as root's key, then This is the node
    // to be deleted
    else
    {
            // node with only one child or no child
            if( (root->left == NULL) || (root->right == NULL) )
            {
                    struct node *temp = root->left ? root->left : root->right;
                    // No child case
                    if(temp == NULL)
                    {
                            temp = root;
                            root = NULL;
                    }
                    else // One child case
                         *root = *temp; // Copy the contents of the non-empty child
                    free(temp);
            }
            else
            {
                    // node with two children: Get the inorder successor (smallest
                    // in the right subtree)
                    struct node* temp = minValueNode(root->right);
                    // Copy the inorder successor's data to this node
                    root->key = temp->key;
                    // Delete the inorder successor
                    root->right = apagaNode(root->right, temp->key);
            }
    }
    // If the tree had only one node then return
    if (root == NULL)
          return root;
    // STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
    root->height = max(height(root->left), height(root->right)) + 1;
    // STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to check whether
    //  this node became unbalanced)
    int balance = getBalance(root);
    // If this node becomes unbalanced, then there are 4 cases
    // Left Left Case
    if (balance > 1 && getBalance(root->left) >= 0)
            return rightRotate(root);
    // Left Right Case
    if (balance > 1 && getBalance(root->left) < 0)
    {
            root->left =  leftRotate(root->left);
            return rightRotate(root);
    }
    // Right Right Case
    if (balance < -1 && getBalance(root->right) <= 0)
            return leftRotate(root);
    // Right Left Case
    if (balance < -1 && getBalance(root->right) > 0)
    {
            root->right = rightRotate(root->right);
            return leftRotate(root);
    }
    return root;
}

int imprime(struct node *root,int targetPos,int curPos)
{
    if(root != NULL)
    {
            int newPos = imprime(root->left, targetPos, curPos);
            newPos++;
            if (newPos == targetPos)
            {
                    printf("%d\n", root->key);
            }
            return imprime(root->right, targetPos, newPos);
    }
    else
    {
            return curPos;
    }
}

int main()
{
  struct node *root = NULL;
  int total=0;
  int n,b;
  string a;
  cin >> n;
  for (int i=0; i<n; i++)
  {
          cin >> a >> b;
          if(a=="INS")
                  {root = insert(root, b);total=total+1;}
          else
          if(a=="REM")
                   {root = apagaNode(root, b);total=total-1;}
          else
                  imprime(root, total-b+1, 0);
  }
    return 0;
}

问题是这个函数非常慢,我不能使用它。在这样一个给定的位置上打印的最佳方式是什么?(A听说过,计算n_节点,在旋转过程中我必须递增、递减,我真的不明白。请帮帮我!给出一些提示和建议)(PS:我不是这类算法的专家)

你听到的建议是正确的:你应该在
节点
结构中添加一个节点计数器:

struct node
{
    int key;
    struct node *left;
    struct node *right;
    int height;
    int n_nodes;
};
它应该包含树中的节点数。假设它是正确的,您可以改进查找具有目标位置的节点的算法:它将准确地知道在树的哪个分支中查找(
),这将使搜索速度更快(当前
impime
实现为O(n))

那么,如何使
n_nodes
字段保持正确的值呢?幸运的是,您已经有了一个示例:
height
。查看现有代码对其进行了哪些更改;这些大概也是您必须更新
n_节点
的地方。其中大多数都是琐碎的(只需添加1);更有趣的是旋转函数:

struct node *rightRotate(struct node *y)
{
    struct node *x = y->left;
    struct node *T2 = x->right;
    // Perform rotation
    x->right = y;
    y->left = T2;
    // Update heights
    y->height = max(height(y->left), height(y->right))+1;
    x->height = max(height(x->left), height(x->right))+1;
    // Update numbers of nodes
    x->n_nodes = ...;
    y->n_nodes = ...;
    T2->n_nodes = ...;
    // Return new root
    return x;
}
所以它会像这样变换树:

8 (N-> N Numbers)
INS 100 (Add 100 to the tree)
INS 200 (Add 200 to the tree)
INS 300 (Add 300 to the tree)
REM 200 (Remove the number 200 from the tree)
PER 1 (Have to output the biggest number in the tree-> Shoud print 300)
INS 1000 (Add 1000 to the tree)
PER 1 ((Have to output the biggest number in the tree-> Shoud print 1000))
PER 2 (I have to output the second biggest number so:  300)
    y                   x
   / \                 / \
  x   D               A   y
 / \         ==>         / \
A   T2                  T2  D
   / \                 / \
  B   C               B   C
size of x:      from a+b+c+2       to     a+b+c+d+3
size of y:      from a+b+c+d+3     to     b+c+d+2
size of T2:     unchanged
这里
A
B
C
D
是程序知道其大小的树;让我们将它们的大小表示为
a
b
c
d
。因此,转换会改变这些大小,如下所示:

8 (N-> N Numbers)
INS 100 (Add 100 to the tree)
INS 200 (Add 200 to the tree)
INS 300 (Add 300 to the tree)
REM 200 (Remove the number 200 from the tree)
PER 1 (Have to output the biggest number in the tree-> Shoud print 300)
INS 1000 (Add 1000 to the tree)
PER 1 ((Have to output the biggest number in the tree-> Shoud print 1000))
PER 2 (I have to output the second biggest number so:  300)
    y                   x
   / \                 / \
  x   D               A   y
 / \         ==>         / \
A   T2                  T2  D
   / \                 / \
  B   C               B   C
size of x:      from a+b+c+2       to     a+b+c+d+3
size of y:      from a+b+c+d+3     to     b+c+d+2
size of T2:     unchanged

因此,只需将其转换为代码。

增加节点以存储左子树的大小。然后您得到的是一个具有查找第n个元素的
O(logn)
算法的。使用常规bst,您所能做的最好的事情就是按线性复杂度的顺序迭代树。@user207933在我的回答中,我添加了整个树的大小。保持左子树的大小是否更方便?@anatolyg我认为在节点处存储树的总大小也同样有效。事实上,它使查找反向的第n个(第n个最大的)变得更简单,因为您需要根目录树的大小。当左子树的大小存储在节点中时,根树的总大小必须单独保持。我不必更改左旋转?在哪里我必须改变更多?右旋转、插入和移除?是x->n_节点+=1;y->n_节点-=1;T2->n_节点+=1;好吗?我想我不明白你的建议。我对这棵树有很多困难