山东大学数据结构实验11 搜索树

描述

创建带索引的二叉搜索树类。存储结构使用链表,提供操作:插入、删除、按名次删除、查找、按名次查找、升序输出所有元素。

格式

输入格式

输入第一行一个数字m (m<=1000000),表示有m个操作。
接下来m行,每一行有两个数字a,b:

  • 当输入的第一个数字 a 为 0 时,输入的第二个数字 b 表示向搜索树中插入 b
  • 当输入的第一个数字 a 为 1 时,输入的第二个数字 b 表示向搜索树中查找 b
  • 当输入的第一个数字 a 为 2 时,输入的第二个数字 b 表示向搜索树中删除 b
  • 当输入的第一个数字 a 为 3 时,输入的第二个数字 b 表示查找搜索树中名次为 b 的元素
  • 当输入的第一个数字 a 为 4 时,输入的第二个数字 b 表示删除搜索树中名次为 b 的元素

输出格式

对于输入中的每一种操作,输出执行操作的过程中依次比较的元素值的异或值。

注意

  • 查询与删除操作中,待查询的元素也需要异或入答案中
  • 查找(删除)操作中,如果未找到,或者插入操作,已存在,输出 0(不插入),不需要输出异或和
  • 查找(删除)第b大,如果不存在,输出 0
  • 删除操作中,如果当前元素有两个孩子,替换的为 右子树中最小的,如果只有一个孩子,直接用该孩子替换当前元素,如果没有孩子,直接删除
  • 删除操作的替换过程中所有比较操作不计入答案

样例1

输入

13
0 6
0 7
0 4
0 5
0 1
1 5
0 7
3 3
2 4
1 5
3 4
4 3
0 4

输出

0
6
6
2
2
7
0
7
2
3
1
6
3

样例2

输入

14
0 43
0 17
0 55
0 62
0 57
0 66
0 67
4 5
0 67
0 70
3 6
4 7
0 20
2 43

输出

0
43
43
28
34
34
96
34
0
29
29
91
58
43

限制

1s, 10240KiB for each test case.

提示

  • 查找和删除第k大的元素时,可以先把第k的元素找到,再按照该元素查找和删除
#include <iostream>
#include<cstring>
#include<algorithm>

using namespace std;

template<class K>
struct BSTNode {
    BSTNode *leftChild;
    BSTNode *rightChild;
    K key;
    int index;

    BSTNode() {};

    BSTNode(K theKey) {
        key = theKey;
        leftChild = NULL;
        rightChild = NULL;
        index = 0;
    }

    BSTNode(BSTNode *bst) {
        bst->rightChild = this->rightChild;
        bst->leftChild = this->leftChild;
        bst->key = this->key;
        bst->index = this->index;
    }

    BSTNode(const K &theElement, BSTNode<K> *theLeft, BSTNode<K> *theRight, int LeftTreeSize) {
        key = theElement;
        leftChild = theLeft;
        rightChild = theRight;
        index = LeftTreeSize;
    }

};

template<class K>
class BSTWithIndex {
public:
    BSTWithIndex() {
        root =NULL;
        Treesize=0;
    };

    //插入、删除、按名次删除、查找、按名次查找、升序输出所有元素。
    int insert(K theKey);

    int erase(K theKey);

    int eraseWithIndex(int theIndex);

    int find(K theKey);

    int findWithIndex(int theIndex);

    void out();

private:
    int Treesize;
    BSTNode<K> *root;

};

template<class K>
int BSTWithIndex<K>::insert(K theKey) {
    BSTNode<K> *currentNode = root;
    BSTNode<K>  *parent = NULL;
    int sum = 0;

    while (currentNode != NULL) {
        if (theKey < currentNode->key) {
            sum ^= currentNode->key;
            parent = currentNode;
            currentNode = currentNode->leftChild;
        } else if (theKey > currentNode->key) {
            sum ^= currentNode->key;
            parent = currentNode;
            currentNode = currentNode->rightChild;
        } else if (theKey == currentNode->key){
            return 0;
        }
    }
    BSTNode<K> *newNode = new BSTNode<K>(theKey);
    if (parent != NULL) {
        if (parent->key > theKey)
            parent->leftChild = newNode;
        else
            parent->rightChild = newNode;
    } else {
        root = newNode;
    }
    Treesize++;
    currentNode = root;
    while (currentNode->key != theKey) {
        if (currentNode->key < theKey) {
            currentNode = currentNode->rightChild;
        } else if (currentNode->key > theKey) {
            currentNode->index++;
            currentNode = currentNode->leftChild;
        }
    }
    return sum;
}

template<class K>
int BSTWithIndex<K>::erase(K theKey) {
    BSTNode<K> *currentNode = root;
    BSTNode<K> *parent = NULL;
    int sum = 0;
    while (currentNode != NULL && currentNode->key != theKey) {
        sum ^= currentNode->key;
        parent = currentNode;
        if (currentNode->key < theKey) {
            currentNode = currentNode->rightChild;
        } else if (currentNode->key > theKey) {
            currentNode = currentNode->leftChild;
        }
    }
    if (currentNode == NULL) {
        return 0;
    }
    sum ^= currentNode->key;
    currentNode = root;
    while (currentNode != NULL && currentNode->key != theKey) {
        if (currentNode->key < theKey) {
            currentNode = currentNode->rightChild;
        } else if (currentNode->key > theKey) {
            currentNode->index--;
            currentNode = currentNode->leftChild;
        }
    }

    if (currentNode->leftChild != NULL && currentNode->rightChild != NULL) {
        BSTNode<K> *ps = currentNode->rightChild;
        BSTNode<K> *s = currentNode;
        while (ps->leftChild != NULL) {
            ps->index--;
            s = ps;
            ps = ps->leftChild;
        }

        BSTNode<K> *newNode = new BSTNode<K>(ps->key, currentNode->leftChild, currentNode->rightChild,
                                             currentNode->index);
        if (parent == NULL)
            root = newNode;
        else if (currentNode == parent->leftChild)
            parent->leftChild = newNode;
        else
            parent->rightChild = newNode;

        if (s == currentNode)
            parent = newNode;
        else
            parent = s;

        delete currentNode;
        currentNode = ps;
    }

    BSTNode<K> *c;
    if (currentNode->leftChild != NULL)
        c = currentNode->leftChild;
    else
        c = currentNode->rightChild;
    if (currentNode == root)
        root = c;
    else {
        if (currentNode == parent->leftChild)
            parent->leftChild = c;
        else
            parent->rightChild = c;
    }
    Treesize--;
    return sum;

}

template<class K>
int BSTWithIndex<K>::eraseWithIndex(int theIndex) {
    BSTNode<K> *currentNode = root;
    BSTNode<K> *parent = NULL;
    int sum = 0;
    while (currentNode != NULL && currentNode->index != theIndex) {
        sum ^= currentNode->key;
        parent = currentNode;
        if (currentNode->index > theIndex) {
            currentNode = currentNode->leftChild;
        } else if (currentNode->index < theIndex) {
            theIndex = theIndex - currentNode->index - 1;
            currentNode = currentNode->rightChild;
        }
    }
    if (currentNode == NULL)
        return 0;
    sum ^= currentNode->key;
    int theElement = currentNode->key;
    currentNode = root;
    while (currentNode != NULL && currentNode->key != theElement) {
        if (currentNode->key < theElement) {
            currentNode = currentNode->rightChild;
        } else if (currentNode->key > theElement) {
            currentNode->index--;
            currentNode = currentNode->leftChild;
        }
    }

    if (currentNode->leftChild != NULL && currentNode->rightChild != NULL) {
        BSTNode<K> *ps = currentNode->rightChild;
        BSTNode<K> *s = currentNode;
        while (ps->leftChild != NULL) {
            ps->index--;
            s = ps;
            ps = ps->leftChild;
        }

        BSTNode<K> *newNode = new BSTNode<K>(ps->key, currentNode->leftChild, currentNode->rightChild, currentNode->index);
        if (parent == NULL)
            root = newNode;
        else if (currentNode == parent->leftChild)
            parent->leftChild = newNode;
        else
            parent->rightChild = newNode;

        if (s == currentNode)
            parent = newNode;
        else
            parent = s;

        delete currentNode;
        currentNode = ps;
    }

    BSTNode<K> *c;
    if (currentNode->leftChild != NULL)
        c = currentNode->leftChild;
    else
        c = currentNode->rightChild;

    if (currentNode == root)
        root = c;
    else {
        if (currentNode == parent->leftChild)
            parent->leftChild = c;
        else
            parent->rightChild = c;
    }
    Treesize--;
    delete currentNode;
    return sum;


}

template <class K>
int BSTWithIndex<K>::find(K theKey)
{
   BSTNode<K>* currentNode = root;
    int sum = 0;
    while (currentNode != NULL && currentNode->key != theKey)
    {
        sum ^= currentNode->key;
        if (currentNode->key > theKey)
        {
            currentNode = currentNode->leftChild;
        }
        else if (currentNode->key < theKey)

        {
            currentNode = currentNode->rightChild;
        }
    }
    if (currentNode == NULL)
        return 0;
    else
    {
        sum ^= currentNode->key;
        return sum;
    }
}


template<class K>
int BSTWithIndex<K>::findWithIndex(int theIndex) {
    BSTNode<K> *p = root;
    int sum = 0;
    while (p != NULL && p->index != theIndex) {
        sum ^= p->key;
        if (p->index > theIndex) {
            p = p->leftChild;
        } else if (p->index < theIndex) {
            theIndex = theIndex - p->index - 1;
            p = p->rightChild;
        }
    }
    if (p == NULL)
        return 0;
    else {
        sum ^= p->key;
        return sum;
    }

}

void inorderHelper(BSTNode<int> *root) {
    if (root == NULL)return;
    inorderHelper(root->leftChild);
    cout << root->key << " ";
    inorderHelper(root->rightChild);
}


int main() {
    int m;
    scanf("%d", &m);
    BSTWithIndex<int> B;
    int a, b;
    while (m--) {
        scanf("%d%d", &a, &b);
        switch (a) {
            case 0:
                cout << B.insert(b) << endl;
                break;
            case 1:
                cout << B.find(b) << endl;
                break;
            case 2:
                cout << B.erase(b) << endl;
                break;
            case 3:
                b--;
                cout << B.findWithIndex(b) << endl;
                break;
            case 4:
                b--;
                cout << B.eraseWithIndex(b) << endl;
                break;


        }
    }


    return 0;
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 山东大学数据结构课程设计要求实现AVL。 AVL是一种自平衡二叉搜索,具有良好的平衡性。在AVL中,每个节点的左子和右子的高度差不超过1。这种平衡性使得AVL的查找、插入和删除操作的时间复杂度都为O(logn),相较于其他平衡二叉搜索如红黑而言,AVL的查找性能更好。 实现AVL主要包括以下几个步骤: 1. 定义AVL的节点结构,包含数据域和左右子节点指针。 2. 实现AVL的插入操作。插入操作首先按照二叉搜索的规则找到要插入的位置,然后进行平衡调整。插入操作的平衡调整包括修改各个节点的平衡因子,根据不同的情况进行的旋转操作,以保证的平衡性。 3. 实现AVL的删除操作。删除操作首先按照二叉搜索的规则找到要删除的节点,然后进行平衡调整。删除操作的平衡调整包括修改各个节点的平衡因子,并根据不同的情况进行的旋转操作,以保证的平衡性。 4. 实现AVL的查找操作。查找操作按照二叉搜索的规则进行,即根据节点的大小关系不断在左子或右子中查找,直到找到目标节点或者为空节点。 在实现AVL的过程中,需要注意保持的平衡性,并根据旋转操作的具体情况进行适当的调整。此外,还可以实现一些辅助函数,如计算节点的高度、更新节点的平衡因子等,以提高代码的可读性和维护性。 总之,山东大学数据结构课程设计要求实现AVL,通过定义节点结构和实现插入、删除和查找操作,可以实现一个具有良好平衡性和高效性能的AVL。 ### 回答2: 山东大学数据结构课程设计中,我实现了AVL。 AVL是一种平衡二叉搜索,它的目的是保持的平衡,以避免在搜索、插入和删除操作中产生较高的时间复杂度。AVL通过在每个节点上维护一个平衡因子(即左子高度减去右子高度),来确保的平衡。 在我的实现中,首先我定义了一个AVLNode结构体,它包含了存储在节点中的数据以及两个指向左右子节点的指针。然后,我实现了一些基本操作函数,包括实现了插入函数、删除函数、查找函数等等。 在插入函数中,我通过递归地将新节点插入到中,并在插入完成后更新每个节点的平衡因子。这样,如果平衡因子超过了允许的范围(例如-1到1之外),我就需要进行相应的旋转操作来恢复的平衡。 在删除函数中,我首先找到要删除的节点,并按照BST的规则进行删除操作。删除后,我还需要更新其父节点及其祖先节点的平衡因子,并通过旋转操作来保持的平衡性。 除了插入和删除操作,我还实现了一些其他的功能,例如查找最小值、查找最大值、查找后继节点、查找前驱节点等。 在整个实现过程中,我注重了代码的可读性和效率。我使用了递归来处理的节点,利用平衡因子来判断的平衡性,采用适当的旋转操作来维持的平衡。通过测试样例,我验证了实现的正确性和性能。 ### 回答3: AVL是一种自平衡的二叉搜索,它的设计旨在解决二叉搜索在插入、删除等操作过程中可能导致不平衡的问题。 在山东大学数据结构课程设计中,我们可以采用以下步骤实现AVL: 1. 首先,我们需要定义AVL的节点结构,该结构包括左右孩子指针、平衡因子和关键字等信息。可以使用结构体来表示节点。 2. 接着,我们实现插入操作。当插入一个新的节点时,我们需要按照二叉搜索的规则找到插入位置,并将节点插入到相应的位置。插入完成后,我们需要逐级向上更新每个节点的平衡因子,并检查是否需要进行旋转操作。 3. 为了保持的平衡性,我们需要定义旋转操作。主要有四种旋转操作:左单旋、右单旋、左-右双旋和右-左双旋。这些旋转操作能够通过改变节点之间的链接关系,使重新平衡。 4. 我们还需要实现删除操作。删除节点时,我们首先找到要删除的节点,并根据二叉搜索的规则调整的结构。删除完成后,同样需要逐级向上更新每个节点的平衡因子,并检查是否需要进行旋转操作。 5. 最后,我们需要实现一些辅助函数,如计算的高度、查找最小值和最大值等。 在实现AVL时,需要注意维护的平衡性,并确保插入和删除操作的正确性。此外,可在实现过程中添加必要的错误处理、输入验证和合理的注释,以提高代码的稳定性和可读性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咕噜咕噜咕噜128

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值