静态列表BST树的简单功能实现

BST树的创建方法其实在网上随便一搜就能搜到好多的,不过网上的BST树基本都是使用链表实现。其实使用静态列表个人觉得没什么用处,不过还是写一下来锻炼自己对数组的一些操作。

1,存储方式

当然使用数组来存了。我先定义了两个常数

  • MAXSIZE 数组的最大值
  • DEFAULT_VALUE 未使用某结点时将其值设为该默认值

类中的数组名我起为tree_list

2,创建方法

1)获得孩子坐标

因为数组的下标从0开始,所以经简单推导可以得到

int SeqBST::leftIndex(int index) {
    return 2 * index + 1;
}

int SeqBST::rightIndex(int index) {
    return 2 * index + 2;
}

2)父亲结点

父亲结点其实也可以通过下标运算得到

int SeqBST::parentIndex(int index) {
    return (index - 1) / 2;
}

3)定义添加节点函数

方法差不多,静态数组是通过下标寻址

void SeqBST::addValue(int val) {
    // 如果未创建树则新建根结点并赋值
    if (tree_list[0] == DEFAULT_VALUE) {
        tree_list[0] = val;
        return;
    }
    // 通过curr找到数值添加位置
    int curr = 0;
    while (true) {
        // 如果curr处的值大于val,则说明val应添加在curr和左孩子上
        if (tree_list[curr] > val) {
            int left = leftIndex(curr);
            // 左孩子不为空则在其左孩子处继续寻找位置
            if (tree_list[left] != DEFAULT_VALUE) {
                curr = left;
                continue;
            }
            // 左孩子为空则在该处插入val并退出循环
            else {
                tree_list[left] = val;
                break;
            }
        }
        // 和上面类似
        else if (tree_list[curr] < val) {
            int right = rightIndex(curr);
            if (tree_list[right] != DEFAULT_VALUE) {
                curr = right;
                continue;
            }
            else {
                tree_list[right] = val;
                break;
            }
        }
    }
}

4)初始化BST树

当然首先要初始化数组,这里给出两种方法

  1. 提供数组
SeqBST::SeqBST(int* arr, int size) {
    tree_list = new int[MAXSIZE];
    for (int i = 0; i < MAXSIZE; i++) {
        tree_list[i] = DEFAULT_VALUE;
    }
    this->size = size;
    for (int i = 0; i < size; i++) {
        this->addValue(arr[i]);
    }
}
  1. 提供vector
SeqBST::SeqBST(std::vector<int> vec) {
    tree_list = new int[MAXSIZE];
    for (int i = 0; i < MAXSIZE; i++) {
        tree_list[i] = DEFAULT_VALUE;
    }
    this->size = vec.size();
    for (auto iter : vec) {
        this->addValue(iter);
    }
}

3,一些方法

1)中序遍历

我用的递归,不多说上代码

void SeqBST::inOrder() {
    inOrder(0);
    std::cout << std::endl;
}
void SeqBST::inOrder(int index) {
    if (tree_list[index] == DEFAULT_VALUE) {
        return;
    }
    inOrder(leftIndex(index));

    std::cout << tree_list[index] << " ";
    inOrder(rightIndex(index));
}

2)删除结点

静态列表删除结点挺让人头疼的,
其实删除结点后最重要的时如何处理其左右两个子树,我先定义了一个move函数,其作用是将以curr为根的子树移到以ptr为根的子树上(准确来说是覆盖)我使用层序遍历来移动子树,不管curr的子树是不是空的都复制到ptr的子树下,如果连续多个移动的结点值都为DEFAULT_VALUE则说明子树全部移动完毕

void SeqBST::move(int curr, int ptr) {
// 使用层序遍历来移动子树来确保子树能够全部转移
    std::queue<int> curr_queue;
    std::queue<int> ptr_queue;
    curr_queue.push(curr);
    ptr_queue.push(ptr);
    int flag = 0;
    int depth_flag = 0;
    while (!curr_queue.empty()) {
        depth_flag += 2;
        if (flag > sqrt(depth_flag)) {
            break;
        }
        int cur_ = curr_queue.front();
        int ptr_ = ptr_queue.front();
        if (tree_list[cur_] != DEFAULT_VALUE || tree_list[ptr_] != DEFAULT_VALUE) {
            flag = 0;
        }
        if (tree_list[cur_] == DEFAULT_VALUE && tree_list[ptr_] == DEFAULT_VALUE) {
            flag++;
        }
        curr_queue.push(rightIndex(cur_));
        curr_queue.push(leftIndex(cur_));
        ptr_queue.push(rightIndex(ptr_));
        ptr_queue.push(leftIndex(ptr_));
        tree_list[ptr_] = tree_list[cur_];
        tree_list[cur_] = DEFAULT_VALUE;
        curr_queue.pop();
        ptr_queue.pop();
}

ptr原有的子树会被curr的子树覆盖

然后就来删除结点,思路和链式存储其实有点像

bool SeqBST::deleteNode(int val) {
    int ptr = findNode(val);
    // 判断是否找到该结点
    if (ptr == -1) { return false; }
    // 如果ptr为叶子结点直接删除
    if (isLeaf(ptr)) {
        tree_list[ptr] = DEFAULT_VALUE;
        return true;
    }
    // 如果只有左孩子
    else if (tree_list[rightIndex(ptr)] == DEFAULT_VALUE) {
        this->move(leftIndex(ptr), ptr);
        return true;
    }
    // 如果只有右孩子
    else if (tree_list[leftIndex(ptr)] == DEFAULT_VALUE) {
        this->move(rightIndex(ptr), ptr);
        return true;
    }
    // 既有左孩子又有右孩子
    else {
        int curr = rightIndex(ptr);
        while (tree_list[curr] != DEFAULT_VALUE) {
            curr = leftIndex(curr);
        }
        this->move(leftIndex(ptr), curr);

        this->move(rightIndex(ptr), ptr);
    }
    return true;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值