树
树是由边连接的节点组成的分层数据结构。每棵树都有一个根节点和零个或多个子树。树在计算机科学中是基础性的,用于组织数据、搜索、排序和表示分层关系。
常见应用包括文件系统、表达式解析、决策树和数据库索引。特别是二叉树,为许多高效算法奠定了基础。
二叉树基础
二叉树是每个节点最多有两个子节点的树,通常称为左子节点和右子节点:
二叉树实现
#include <iostream>
#include <queue>
using namespace std;
struct TreeNode {
int data;
TreeNode* left;
TreeNode* right;
TreeNode(int value) : data(value), left(nullptr), right(nullptr) {}
};
class BinaryTree {
private:
TreeNode* root;
// Helper function for inorder traversal
void inorderHelper(TreeNode* node) {
if (node != nullptr) {
inorderHelper(node->left);
cout << node->data << " ";
inorderHelper(node->right);
}
}
// Helper function for preorder traversal
void preorderHelper(TreeNode* node) {
if (node != nullptr) {
cout << node->data << " ";
preorderHelper(node->left);
preorderHelper(node->right);
}
}
// Helper function for postorder traversal
void postorderHelper(TreeNode* node) {
if (node != nullptr) {
postorderHelper(node->left);
postorderHelper(node->right);
cout << node->data << " ";
}
}
// Helper function to calculate height
int heightHelper(TreeNode* node) {
if (node == nullptr) return -1;
return 1 + max(heightHelper(node->left), heightHelper(node->right));
}
// Helper function to delete tree
void deleteTree(TreeNode* node) {
if (node != nullptr) {
deleteTree(node->left);
deleteTree(node->right);
delete node;
}
}
public:
BinaryTree() : root(nullptr) {}
~BinaryTree() {
deleteTree(root);
}
// Insert using level-order (breadth-first)
void insert(int value) {
TreeNode* newNode = new TreeNode(value);
if (root == nullptr) {
root = newNode;
return;
}
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
TreeNode* current = q.front();
q.pop();
if (current->left == nullptr) {
current->left = newNode;
return;
} else if (current->right == nullptr) {
current->right = newNode;
return;
} else {
q.push(current->left);
q.push(current->right);
}
}
}
// Tree traversals
void inorderTraversal() {
cout << "Inorder: ";
inorderHelper(root);
cout << endl;
}
void preorderTraversal() {
cout << "Preorder: ";
preorderHelper(root);
cout << endl;
}
void postorderTraversal() {
cout << "Postorder: ";
postorderHelper(root);
cout << endl;
}
// Level-order traversal (breadth-first)
void levelOrderTraversal() {
if (root == nullptr) return;
cout << "Level-order: ";
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
TreeNode* current = q.front();
q.pop();
cout << current->data << " ";
if (current->left) q.push(current->left);
if (current->right) q.push(current->right);
}
cout << endl;
}
int height() {
return heightHelper(root);
}
};
int main() {
BinaryTree tree;
// Insert nodes
tree.insert(1);
tree.insert(2);
tree.insert(3);
tree.insert(4);
tree.insert(5);
cout << "Tree traversals:" << endl;
tree.inorderTraversal();
tree.preorderTraversal();
tree.postorderTraversal();
tree.levelOrderTraversal();
cout << "Tree height: " << tree.height() << endl;
return 0;
}二叉搜索树 (BST)
二叉搜索树是一种二叉树,其中左子树包含值小于根节点的节点,右子树包含值大于根节点的节点:
二叉搜索树实现
#include <iostream>
using namespace std;
struct BSTNode {
int data;
BSTNode* left;
BSTNode* right;
BSTNode(int value) : data(value), left(nullptr), right(nullptr) {}
};
class BST {
private:
BSTNode* root;
BSTNode* insertHelper(BSTNode* node, int value) {
if (node == nullptr) {
return new BSTNode(value);
}
if (value < node->data) {
node->left = insertHelper(node->left, value);
} else if (value > node->data) {
node->right = insertHelper(node->right, value);
}
// If value equals node->data, we don't insert (no duplicates)
return node;
}
BSTNode* searchHelper(BSTNode* node, int value) {
if (node == nullptr || node->data == value) {
return node;
}
if (value < node->data) {
return searchHelper(node->left, value);
} else {
return searchHelper(node->right, value);
}
}
BSTNode* findMin(BSTNode* node) {
while (node && node->left) {
node = node->left;
}
return node;
}
BSTNode* deleteHelper(BSTNode* node, int value) {
if (node == nullptr) return node;
if (value < node->data) {
node->left = deleteHelper(node->left, value);
} else if (value > node->data) {
node->right = deleteHelper(node->right, value);
} else {
// Node to be deleted found
if (node->left == nullptr) {
BSTNode* temp = node->right;
delete node;
return temp;
} else if (node->right == nullptr) {
BSTNode* temp = node->left;
delete node;
return temp;
}
// Node with two children
BSTNode* temp = findMin(node->right);
node->data = temp->data;
node->right = deleteHelper(node->right, temp->data);
}
return node;
}
void inorderHelper(BSTNode* node) {
if (node != nullptr) {
inorderHelper(node->left);
cout << node->data << " ";
inorderHelper(node->right);
}
}
void deleteTree(BSTNode* node) {
if (node != nullptr) {
deleteTree(node->left);
deleteTree(node->right);
delete node;
}
}
public:
BST() : root(nullptr) {}
~BST() {
deleteTree(root);
}
void insert(int value) {
root = insertHelper(root, value);
}
bool search(int value) {
return searchHelper(root, value) != nullptr;
}
void remove(int value) {
root = deleteHelper(root, value);
}
void inorderTraversal() {
cout << "BST (sorted): ";
inorderHelper(root);
cout << endl;
}
};
int main() {
BST bst;
// Insert values
int values[] = {50, 30, 70, 20, 40, 60, 80};
for (int val : values) {
bst.insert(val);
}
bst.inorderTraversal(); // Should print in sorted order
// Search
cout << "Search 40: " << (bst.search(40) ? "Found" : "Not Found") << endl;
cout << "Search 25: " << (bst.search(25) ? "Found" : "Not Found") << endl;
// Delete
bst.remove(30);
cout << "After deleting 30: ";
bst.inorderTraversal();
return 0;
}树的应用
表达式树
表达式树表示数学表达式,其中操作符是内部节点,操作数是叶子节点:
表达式树求值
#include <iostream>
#include <stack>
#include <string>
using namespace std;
struct ExprNode {
string data;
ExprNode* left;
ExprNode* right;
ExprNode(string value) : data(value), left(nullptr), right(nullptr) {}
};
class ExpressionTree {
private:
ExprNode* root;
bool isOperator(string str) {
return str == "+" || str == "-" || str == "*" || str == "/";
}
int evaluate(ExprNode* node) {
if (node == nullptr) return 0;
// If leaf node (operand)
if (!isOperator(node->data)) {
return stoi(node->data);
}
// Evaluate left and right subtrees
int leftVal = evaluate(node->left);
int rightVal = evaluate(node->right);
// Apply operator
if (node->data == "+") return leftVal + rightVal;
if (node->data == "-") return leftVal - rightVal;
if (node->data == "*") return leftVal * rightVal;
if (node->data == "/") return leftVal / rightVal;
return 0;
}
void inorderHelper(ExprNode* node) {
if (node != nullptr) {
if (isOperator(node->data)) cout << "(";
inorderHelper(node->left);
cout << node->data;
inorderHelper(node->right);
if (isOperator(node->data)) cout << ")";
}
}
public:
ExpressionTree() : root(nullptr) {}
// Build expression tree from postfix expression
void buildFromPostfix(vector<string> postfix) {
stack<ExprNode*> st;
for (string token : postfix) {
ExprNode* node = new ExprNode(token);
if (isOperator(token)) {
node->right = st.top(); st.pop();
node->left = st.top(); st.pop();
}
st.push(node);
}
root = st.top();
}
int evaluateExpression() {
return evaluate(root);
}
void printInfix() {
cout << "Infix expression: ";
inorderHelper(root);
cout << endl;
}
};
int main() {
ExpressionTree tree;
// Postfix expression: "2 3 + 4 *" represents (2 + 3) * 4
vector<string> postfix = {"2", "3", "+", "4", "*"};
tree.buildFromPostfix(postfix);
tree.printInfix();
cout << "Result: " << tree.evaluateExpression() << endl;
// Another example: "15 7 1 1 + - / 3 * 2 1 1 + + -"
vector<string> complex = {"15", "7", "1", "1", "+", "-", "/", "3", "*", "2", "1", "1", "+", "+", "-"};
ExpressionTree complexTree;
complexTree.buildFromPostfix(complex);
complexTree.printInfix();
cout << "Result: " << complexTree.evaluateExpression() << endl;
return 0;
}