Мне нужно построить структуру данных, которая:
- выучить x (вставить x)
- забыть x (удаляет x). если x отсутствует, ничего не делать
- уменьшить xn - уменьшить счетчик x на n, если n> = count, то узел просто удаляется. и если x не присутствует, то ничего не делать
- less_nums x - найти количество узлов (с учетом их кратности), которые меньше x
- больший_nums x - аналогично 4., но больше
- как c k - вывести k-й элемент в порядке возрастания (с учетом кратности), вывести -1, если k> общее количество узлов
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;
}
Я просматривал свой код несколько раз и не смог выяснить, в чем дело