我需要建立一个数据结构:
1≤q≤5 * 10 ^ 5
1≤x≤10 ^ 9
我为此构建了一个AVL树,为此是否有更好,更简单的数据结构?
我的代码对于给定的输入和输出正常工作:
Input: 14 learn 5 learn 2 learn 7 learn 3 learn 2 smaller_nums 5 larger_nums 2 asc 2 decrease 2 1 asc 2 forget 7 larger_nums 2 forget 5 larger_nums 2 Output: 3 3 2 3 2 1
[我提交时,我通过了4/9个测试用例。我得到2个测试用例的错误答案,以及3个测试用例的超时。
#include <stdio.h> #include <stdlib.h> long int N=0; //keeps count of total number nodes, this value is used in asc function only // An AVL tree node struct node { long int key; struct node* left; struct node* right; long int height; long int count; }; // A utility function to get height of the tree long int height(struct node* N) { if (N == NULL) return 0; return N->height; } // A utility function to get maximum of two integers long int max(long int a, long 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(long 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 node->count = 1; 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 long int getBalance(struct node* N) { if (N == NULL) return 0; return height(N->left) - height(N->right); } struct node* insert(struct node* node, long int key) { /* 1. Perform the normal BST rotation */ if (node == NULL) { N++; return (newNode(key)); } // If key already exists in BST, increment count and return if (key == node->key) { (node->count)++; N++; return node; } /* Otherwise, recur down the tree */ 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 */ long 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* forgetNode(struct node* root, long 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 = forgetNode(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 = forgetNode(root->right, key); // if key is same as root's key, then This is the node // to be deleted else { N += -(root->count); // If key is present more than once, simply decrement // count and return // Else, delete the node // 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 and update the count root->key = temp->key; root->count = temp->count; temp->count = 1; // Delete the inorder successor root->right = forgetNode(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) long 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; } struct node* decreaseNode(struct node* root, long int key, long int n) { // 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 = decreaseNode(root->left, key, n); // 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 = decreaseNode(root->right, key, n); // if key is same as root's key, then This is the node // to be deleted else { // If key is present more than once, simply decrement // count and return if (root->count > 1 && n < root->count) { (root->count) += -n; N += -n; return root; } // Else, delete the node // node with only one child or no child N += -(root->count); 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 and update the count root->key = temp->key; root->count = temp->count; temp->count = 1; // Delete the inorder successor root->right = decreaseNode(root->right, temp->key, n); } } // 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) long 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; } // Convinience function to travers the tree in ascending order void inOrder(struct node* root) { if (root != NULL) { inOrder(root->left); printf("%ld(%ld) ", root->key, root->count); inOrder(root->right); } } // Find out number of larger nodes void largerNums(struct node* root, long int key, long int* lnums){ if (root == NULL) return; if (key < root->key){ (*lnums) += root->count; largerNums(root->right, key, lnums); largerNums(root->left, key, lnums); } else if (key >= root->key) largerNums(root->right, key, lnums); return; } // Find out number of smaller nodes void smallerNums(struct node* root, long int key, long int* snums){ if (root == NULL) return; if (key <= root->key){ smallerNums(root->left, key, snums); } else if (key > root->key){ (*snums) += root->count; smallerNums(root->left, key, snums); smallerNums(root->right, key, snums); } return; } // Prints k'th element in ascending order void asc(struct node* root, long int key, long int* cnt){ if (root != NULL) { asc(root->left, key, cnt); int i; for(i=1; i <= (root->count); ++i){ (*cnt)++; if(*cnt == key){ printf("%ld\n", root->key); return; } } asc(root->right, key, cnt); } } // Function to compare strings int myStrCompare(char a[], char b[]){ int c = 0; while (a[c] == b[c]) { if (a[c] == '\0' || b[c] == '\0') break; c++; } if (a[c] == '\0' && b[c] == '\0') return 0; else return -1; } // Function to know what command entered by user int myCompare(char *str){ if(myStrCompare(str, "learn") == 0) return 1; else if(myStrCompare(str, "forget") == 0) return 2; else if(myStrCompare(str, "decrease") == 0) return 3; else if(myStrCompare(str, "smaller_nums") == 0) return 4; else if(myStrCompare(str, "larger_nums") == 0) return 5; else if(myStrCompare(str, "asc") == 0) return 6; return -1; } /* Driver program to test above function*/ int main() { long int i, q, x, n, lnums, snums, cnt; int choice; char input[100]; struct node* root= NULL; scanf("%ld", &q); //printf("%s", input); for(i=1; i<=q; ++i){ scanf("%s", input); //printf("%s", input); choice = myCompare(input); //printf("\n%d", choice); switch(choice){ case 1: scanf("%ld", &x); //printf("\nEntered x\n: %d", x); root = insert(root, x); /* printf("\n"); inOrder(root); printf("\n");*/ break; case 2: scanf("%ld", &x); //printf("\nEntered x\n: %d", x); root = forgetNode(root, x); /*printf("\n"); inOrder(root); printf("\n");*/ break; case 3: scanf("%ld%ld", &x, &n); //printf("\nEntered x\n: %d", x); if(n < 1){ break; }else{ root = decreaseNode(root, x, n); } /* printf("\n"); inOrder(root); printf("\n");*/ break; case 4: scanf("%ld", &x); //printf("\nEntered x\n: %d", x); snums = 0; smallerNums(root, x, &snums); /*printf("\n"); inOrder(root); printf("\n");*/ printf("%ld\n", snums); break; case 5: scanf("%ld", &x); //printf("\nEntered x\n: %d", x); lnums = 0; largerNums(root, x, &lnums); /*printf("\n"); inOrder(root); printf("\n");*/ printf("%ld\n", lnums); break; case 6: scanf("%ld", &x); if(x > N){ printf("%d\n", -1); break; }else{ //printf("\nEntered x\n: %d", x); cnt=0; asc(root, x, &cnt); } /*printf("\n"); inOrder(root); printf("\n");*/ break; } } /*root = insert(root, 5); root = insert(root, 2); root = insert(root, 7); root = insert(root, 3); root = insert(root, 2); smallerNums(root, 5, &s); printf("\n%d\n", s); largerNums(root, 2, &l); printf("%d\n", l); inOrderK(root, 2, &cnt); cnt = 0; root = decreaseNode(root, 2, 1); inOrderK(root, 2, &cnt); cnt = 0; root = forgetNode(root, 7); l=0; largerNums(root, 2, &l); printf("%d\n", l); root = forgetNode(root, 5); l=0; largerNums(root, 2, &l); printf("%d\n", l); inOrder(root); l=0; largerNums(root, 1, &l); printf("\n%d\n", l); */ return 0; }
我已经多次查看了我的代码,但无法弄清楚出了什么问题
我需要构建一个数据结构,以:学习x(插入x)忘记x(删除x)。如果x不存在,则不执行任何操作将x n减少-将x的计数减少n,如果n> = count,则该节点就是...
尝试在log(n)时间执行此操作将left_count和right_count放入节点