AVL Tree - Как отследить высоту дерева? Разница между typedef и указателем на структуру - PullRequest
0 голосов
/ 30 августа 2018

Код должен печатать AVL Tree (сбалансированное двоичное дерево). Почему мой код не работает? Ниже приведен код этого сайта и мой. Разница только в определении узла.

Правильная версия:

struct Node
{
    int key;
    struct Node *left;
    struct Node *right;
    int height;
};

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);
}

Моя (неверная) модифицированная версия кода от Modern Compiler Optimalisation:

typedef struct tree *T_tree;
struct tree {
    T_tree left;
    int key;
    T_tree right;
    int height;
    //int size = 0;
};
T_tree Tree (T_tree l, int k, T_tree r) {
    T_tree t = malloc(sizeof(*t));
    t-> left=l;
    t-> key=k;
    t->right = r;
    if (l==NULL &&  r == NULL) {
        t->height = 1;
    }
    /*
    else {
        t->height++;
    }*/
    return t;
}

Полный правильный код с основным:

#include<stdio.h>
#include<stdlib.h>

// 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 the 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);
}

// Recursive function to insert a key in the subtree rooted
// with node and returns the new root of the subtree.
struct Node* insert(struct Node* node, int key)
{
  /* 1.  Perform the normal BST insertion */
  if (node == NULL)
      return(newNode(key));

  if (key < node->key)
      node->left  = insert(node->left, key);
  else if (key > node->key)
      node->right = insert(node->right, key);
  else // Equal keys are not allowed in BST
      return node;

  /* 2. Update height of this ancestor node */
  node->height = 1 + max(height(node->left),
                       height(node->right));

  /* 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;
}


// A utility function to print preorder traversal
// of the tree.
// The function also prints height of every node
void preOrder(struct Node *root)
{
    if(root != NULL)
    {
        printf("%d ", root->key);
        preOrder(root->left);
        preOrder(root->right);
    }
}

/* Drier program to test above function*/
int main()
{
  struct Node *root = NULL;

  /* Constructing tree given in the above figure */
  root = insert(root, 10);
  root = insert(root, 20);
  root = insert(root, 30);
  root = insert(root, 40);
  root = insert(root, 50);
  root = insert(root, 25);

  /* The constructed AVL Tree would be
            30
           /  \
         20   40
        /  \     \
       10  25    50
  */

  printf("Preorder traversal of the constructed AVL"
         " tree is \n");
  preOrder(root);

  return 0;
}

Но это дает неверные значения? Полный неверный код с основным:

#include <stdio.h>
#include <stdlib.h>

typedef struct tree *T_tree;
struct tree {
    T_tree left;
    int key;
    T_tree right;
    int height;
    //int size = 0;
};

T_tree Tree (T_tree l, int k, T_tree r) {
    T_tree t = malloc(sizeof(*t));
    t-> left=l;
    t-> key=k;
    t->right = r;
    if (l==NULL &&  r == NULL) {
        t->height = 1;
    }
    /*
    else {
        t->height++;
    }*/
return t;
}
//bigger of 2 integers:
int max(int a, int b) {
    if (a>=b) {
        return a;
    }
    else {
        return b;
    }
}

//actual height of tree
int height(T_tree t) {
    if (t==NULL)
        return 0;
    return t->height;
}

T_tree rightRotate(T_tree t) {
    T_tree t1 = t->left;
    T_tree t2 = t1->right;
    //rotation:
    t1->right = t;
    t->left = t2;
    //update heights:

    t->height = max(height(t->left), height(t->right))+1;
    t1->height = max(height(t1->left), height(t1->right))+1;

    return t1;
};
T_tree leftRotate(T_tree t) {
    T_tree t1 = t->right;
    T_tree t2 = t1->left;
//rotation:
t1->left = t;
t->right = t2;
//update heights:

t->height = max(height(t->left), height(t->right))+1;
t1->height = max(height(t1->left), height(t1->right))+1;

return t1;
};
//get balance factor of node N
int getBalance(T_tree node) {
    if (node == NULL)
        return 0;
    return height(node->left) - height(node->right);
}

T_tree insert(int key, T_tree t) {
    if (t==NULL) {
        return Tree(NULL, key, NULL);  
    }
    if (key < (t->key)) {
        Tree(insert(key,t->left), t->key, t->right);
    }
    else if (key > t->key) {
        return Tree(t->left, t->key, insert(key, t-> right));
    }
    else return Tree(t->left, key, t-> right);
    //update height of this node
    t->height = 1 + max(height(t->left), height(t->right));
    //is node becomed unbalanced?
    int balance = getBalance(t);
    if (balance >1 && key< t->left->key)
        return rightRotate(t);

    if (balance <-1 && key > t->right->key)
        return leftRotate(t);

    if (balance>1 && key > t->left->key) {
        t->left = leftRotate(t->left);
        return rightRotate(t);
    }
    if (balance < -1 && key < t->right->key) {
        t->right = rightRotate(t->right);
        return leftRotate(t);
    }
    return t;
}

void preOrder(T_tree root)
{
    if(root != NULL)
    {
        printf("%d ", root->key);
        preOrder(root->left);
        preOrder(root->right);
    }
}

int main(int argc, char const *argv[])
{
    T_tree t1 = NULL;
    t1 = insert(10, t1);
    t1 = insert(20, t1);
    t1 = insert(30, t1);
    t1 = insert(40, t1);
    t1 = insert(50, t1);
    t1 = insert(15, t1);
    preOrder(t1);
    return 0;
}

Первая версия с сайта дает правильные значения:

30 20 10 25 40 50

Но второе, если я поставлю 15 в конце основной функции, print игнорирует ее, даже если это та же самая функция печати:

10 20 30 40 50

(Также еще один вопрос: мне нужно было нажать cltr + ka lot, чтобы сделать код доступным для просмотра, почему? Может быть, я должен установить 4 вкладки шириной в пробел в редакторе, который я использую, вот почему вставка не работает точно так же, как это должно?)

...