二叉排序树(Binary Search Tree,简称BST),是一种特殊的二叉树,它具有以下性质:
每个节点都有一个键(Key)和两个子节点,分别称为左子节点和右子节点。
左子节点的键小于其父节点的键,右子节点的键大于其父节点的键。
对每个节点,其左子树和右子树也都是二叉排序树。
当涉及到二叉排序树的插入操作时,我们通常可以使用递归和非递归两种方式来实现。下面将为你详细介绍这两种插入方法的差异,并提供代码示例。
非递归插入
非递归插入是通过迭代的方式实现的,使用循环来遍历树并找到合适的位置进行插入。具体步骤如下:
1.如果树为空,则创建一个新结点作为根结点。
2.否则,从根结点开始,与待插入结点的值进行比较。
· 如果待插入值小于当前结点的值,则进入左子树。
· 如果待插入值大于当前结点的值,则进入右子树。
· 如果待插入值等于当前结点的值,则不进行插入操作(可以根据需要进行处理)。
3.重复步骤2,直到找到一个空位置。
4.在空位置创建一个新结点,将待插入值赋给该结点。
下面是一个示例代码:
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int value) : val(value), left(nullptr), right(nullptr) {}
};void insertNode(TreeNode*& root, int value) {TreeNode* newNode = new TreeNode(value);if (root == nullptr) {root = newNode;return;}TreeNode* curr = root;TreeNode* parent = nullptr;while (curr != nullptr) {parent = curr;if (value < curr->val) {curr = curr->left;} else if (value > curr->val) {curr = curr->right;} else {// 处理结点值相等的情况return;}}if (value < parent->val) {parent->left = newNode;} else {parent->right = newNode;}
}
递归插入
递归插入是通过函数的递归调用实现的,每次递归都会判断当前结点是否为空,从而决定是向左子树还是右子树递归。具体步骤如下:
1.如果树为空,则创建一个新结点作为根结点。
2.否则,与当前结点的值进行比较。
· 如果待插入值小于当前结点的值,则递归调用插入函数,传入当前结点的左子结点。
· 如果待插入值大于当前结点的值,则递归调用插入函数,传入当前结点的右子结点。
· 如果待插入值等于当前结点的值,则不进行插入操作(可以根据需要进行处理)。
3.在递归的最底层,创建一个新结点,将待插入值赋给该结点,并将该结点作为当前结点的子结点。
下面是一个示例代码:
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int value) : val(value), left(nullptr), right(nullptr) {}
};void insertNode(TreeNode*& root, int value) {if (root == nullptr) {root = new TreeNode(value);return;}if (value < root->val) {insertNode(root->left, value);} else if (value > root->val) {insertNode(root->right, value);} else {// 处理结点值相等的情况return;}
}
递归与非递归的差异
1.实现方式:递归方式通过函数栈实现,而非递归方式通过循环实现。
2.代码简洁度:递归方式通常更简洁,代码更容易理解;非递归方式需要更多的控制逻辑,但更灵活。
3.性能:递归方式可能产生更多的函数调用开销,而非递归方式通过迭代实现,性能可能更好。