实现了2-3树结点的插入操作、结点删除操作和前中后序遍历2-3树代码
从0创建一棵2-3树完整代码
两个头文件:NODE.h 和 TREE.h
以及三个源文件
#ifndef NODE_H_INCLUDED
#define NODE_H_INCLUDED
#include <string>
using namespace std;
class Node {
friend class Tree;
private:
string small;
string large;
Node* left;
Node* middle;
Node* right;
Node* parent;
Node();
Node(const string&);
bool isLeaf();
bool isFull();
bool hasKey(const string&);
void insertKey(const string&);
};
#endif // NODE_H_INCLUDED
#ifndef TREE_H_INCLUDED
#define TREE_H_INCLUDED
#include "Node.h"
class Tree {
private:
Node* root;
public:
Tree();
~Tree();
//Inserts a value into tree while following 2-3 tree properties
void insert(const string&);
//Prints tree in pre order
void preOrder() const;
//Prints tree in order
void inOrder() const;
//Prints tree in post order
void postOrder() const;
//Removes node from tree while following 2-3 tree properties
void remove(const string&);
//Returns true if key exists in any node in tree
bool search(const string&) const;
Node* getRoot();
void adjust(Node*) const;
private:
void destroyTree(Node*);//destructor helper
bool searchNode(Node*, const string&) const;//search helper
Node* searchDeleteNode(Node*, const string&) const;
Node* splitNode(Node*, Node*, const string&);//insert helper
Node* splitNode(Node*, Node*, Node*);//insert helper
Node* insert(Node*, const string& key);//insert helper
void insertChildren(Node*, const string&, Node*, Node*);//insert helper
void insertChildren(Node*, Node*, Node*, Node*);//insert helper
void insertLeaf(Node*, const string&);//insert helper
void preOrderTraversal(Node*) const;
void inOrderTraversal(Node*) const;
void postOrderTraversal(Node*) const;
Tree* operator=(Tree* rhs);//Assignment operator
Tree(const Tree& rhs); // Copy Constructor
void remove(Node*, const string&); //remove helper
void remove(Node*);
Node* getPre(Node*,const string& key);
void inOrderTraversal2(Node* node) const;
};
#endif // TREE_H_INCLUDED
#include "Tree.h"
#include <iostream>
using namespace std;
void printOrders(Tree* tree) {
cout << "Preorder = ";
tree->preOrder();
cout << "Inorder= ";
tree->inOrder();
cout << "Postorder = ";
tree->postOrder();
}
int menu() {
int choice = 0;
cout << endl << "Enter menu choice: ";
cout << endl;
cout
<< "1. Insert" << endl
<< "2. Remove" << endl
<< "3. Print" << endl
<< "4. Search" << endl
<< "5. Quit" << endl;
cin >> choice;
// fix buffer just in case non-numeric choice entered
// also gets rid of newline character
cin.clear();
cin.ignore(256, '\n');
return choice;
}
int main() {
Tree tree;
int choice = menu();
string entry;
while (choice != 5) {
if (choice == 1) {
cout << "Enter movie title to insert: ";
getline(cin, entry);
cout << endl;
tree.insert(entry);
tree.adjust(tree.getRoot());
}
else if (choice == 2) {
cout << "Enter movie title to remove: ";
getline(cin, entry);
cout << endl;
tree.remove(entry);
tree.adjust(tree.getRoot());
}
else if (choice == 3) {
printOrders(&tree);
}
else if (choice == 4) {
cout << "Enter movie title to search for: ";
getline(cin, entry);
cout << endl;
if (tree.search(entry)) {
cout << "Found" << endl;
}
else {
cout << "Not Found" << endl;
}
}
//fix buffer just in case non-numeric choice entered
choice = menu();
}
return 0;
}
#include <iostream>
#include <string>
using namespace std;
#include "Node.h"
Node::Node() : small(""), large(""), left(nullptr), middle(nullptr), right(nullptr), parent(nullptr) {}
Node::Node(const string& value) : small(value), large(""), left(nullptr), middle(nullptr), right(nullptr), parent(nullptr) {}
bool Node::isLeaf() {
return (left == nullptr && middle == nullptr && right == nullptr);
}
bool Node::isFull() {
return (!small.empty() && !large.empty());
}
bool Node::hasKey(const string& key) {
return (small == key || large == key);
}
void Node::insertKey(const string& key) {
if (!isFull()) {
if (small.empty()) {
small = key;
}
else if (large.empty()) {
large = key;
}
}
if (small > large) {
swap(small, large);
}
}
#include <iostream>
#include <string>
#include <stdexcept>
#include<vector>
using namespace std;
#include "Tree.h"
string inorder[1000];
int i=0;
// Default constructor
Tree::Tree() {
root = nullptr;
}
Tree::~Tree() {
// Call a private helper function to delete all nodes recursively
destroyTree(root);
}
//Wrapper function for searchNode
bool Tree::search(const string& value) const {
return searchNode(root, value);
}
//Recursively searches through the tree to find matching value
bool Tree::searchNode(Node* node, const string& key) const {
if (node == nullptr) {
return false; //Empty tree or reaches the end of tree
}
if (node->small == key || node->large == key) {
return true;
}
if (node->small.empty()) {
//Should never happen so returns false
return false;
}
//Recursively searches through the tree
if (key < node->small) {
return searchNode(node->left, key);
}
else if(!node->large.empty() && key>node->large){
return searchNode(node->right, key);
}
else {
return searchNode(node->middle, key);
}
}
//Recursively searches through the tree to find matching value
Node* Tree::searchDeleteNode(Node* node, const string& key) const {
if (node == nullptr) {
return nullptr; //Empty tree or reaches the end of tree
}
if (node->small == key || node->large == key) {
return node;
}
if (node->small.empty()) {
//Should never happen so returns false
return nullptr;
}
//Recursively searches through the tree
if (key < node->small) {
return searchDeleteNode(node->left, key);
}
else if(!node->large.empty() && key>node->large){
return searchDeleteNode(node->right, key);
}
else {
return searchDeleteNode(node->middle, key);
}
}
//Helper that recursively frees all node in tree
void Tree::destroyTree(Node* node) {
if (node != nullptr) {
destroyTree(node->left);
destroyTree(node->middle);
destroyTree(node->right);
delete node;
}
}
//Wrapper for insertion
void Tree::insert(const string& key) {
if (search(key)) {
cout<<"exist......"<<endl;
return; //Does not insert anything if there already exists node with key data in the tree
}
//Case 1: Inserting into empty tree
if (root == nullptr) {
root = new Node(key); //Simply makes a new node and set root to point to it
}
else {
insert(root, key);
}
}
//Insertion
Node* Tree::insert(Node* curr, const string& key) {
if (search(key)) {
return nullptr; //Does not insert if duplicate value found
}
//Premptively splits nodes if encountered while inserting
if (curr->isFull() && curr->isLeaf()) {
curr = splitNode(curr, curr->parent, new Node(key));
}
//Locating sutable leaf node for the insertion
else if (!curr->isLeaf()) {
if (key < curr->small) {
return insert(curr->left, key);
}
else if (curr->large == "" || key < curr->large) {
return insert(curr->middle, key);
}
else {
return insert(curr->right, key);
}
}
else {
insertLeaf(curr, key);
return curr;
}
}
void Tree::insertLeaf(Node* curr, const string& key) {
if (search(key)) {
return;
}
else if (key < curr->small) {
curr->large = curr->small;
curr->small = key;
}
else if (key > curr->small) {
curr->large = key;
}
}
//Helper for splitting up nodes
Node* Tree::splitNode(Node* curr, Node* parent, Node* key) {
if (!curr->isFull()) {
return nullptr; //Does nothing if curr is not full hence no need to split
}
Node* splitLeft = nullptr;
Node* splitRight = nullptr;
Node* mid = nullptr;
//记录下左中右
Node* tmpl = curr->left;
Node* tmpm = curr->middle;
Node* tmpr = curr->right;
string midStr;
//插入最左边 中间给右边
if (key->small < curr->small) {
midStr = curr->small;
splitLeft = key;
splitRight = new Node(curr->large);
splitRight->left = tmpm;
splitRight->middle = tmpr;
splitLeft->parent = parent;
splitRight->parent = parent;
if(key->left)
key->left->parent = key;
if(key->middle)
key->middle->parent = key;
}
//插入中间 都要给
else if (key->small > curr->small && key->small < curr->large) {
midStr = key->small;
splitLeft = new Node(curr->small);
splitLeft->left = tmpl;
splitLeft->middle = key->left;
if(key->left)
key->left->parent = splitLeft;
splitRight = new Node(curr->large);
splitRight->left = key->middle;
if(key->middle)
key->middle->parent = splitRight;
splitRight->middle = curr->right;
splitLeft->parent = parent;
splitRight->parent = parent;
}
//插入最右边 给左边
else {
midStr = curr->large;
splitLeft = new Node(curr->small);
splitRight = key;
splitLeft->left = tmpl;
splitLeft->middle = tmpm;
splitLeft->parent = parent;
splitRight->parent = parent;
if(key->left)
key->left->parent = key;
if(key->middle)
key->middle->parent = key;
}
mid = new Node(midStr);
mid->left = splitLeft;
mid->middle = splitRight;
delete curr;
if (parent != nullptr) {
insertChildren(parent, mid, splitLeft, splitRight);
}
else {
parent = mid;
parent->left = splitLeft;
parent->middle = splitRight;
root = parent;
splitLeft->parent = root;
splitRight->parent = root;
}
return parent;
}
//Handles insertion to a node with children that was split as well
void Tree::insertChildren(Node* parent, Node* son, Node* splitLeft, Node* splitRight) {
Node* t;
if(!parent->isFull()){
if (son->small < parent->small) {
parent->large = parent->small;
parent->small = son->small;
parent->left = son->left;
parent->right = parent->middle;
parent->middle = son->middle;
son->left->parent = parent;
son->middle->parent = parent;
}
else {
parent->large = son->small;
parent->left = parent->left;
parent->right = son->middle;
parent->middle = son->left;
son->left->parent = parent;
son->middle->parent = parent;
}
}else{
t = splitNode(parent, parent->parent, son);
}
}
//Wrapper for preOrder
void Tree::preOrder() const {
preOrderTraversal(root);
cout << endl;
}
//Standard pre order traversal
void Tree::preOrderTraversal(Node* node) const {
if (node != nullptr) {
cout << node->small << ", ";
preOrderTraversal(node->left);
if (!node->large.empty()) {
cout << node->large << ", ";
}
preOrderTraversal(node->middle);
preOrderTraversal(node->right);
}
}
//Wrapper for postOrder
void Tree::postOrder() const {
postOrderTraversal(root);
cout << endl;
}
//Standard post order traversal
void Tree::postOrderTraversal(Node* node) const {
if (node != nullptr) {
postOrderTraversal(node->left);
postOrderTraversal(node->middle);
cout << node->small << ", ";
postOrderTraversal(node->right);
if (!node->large.empty()) {
cout << node->large << ", ";
}
}
}
//Wrapper for in order
void Tree::inOrder() const {
inOrderTraversal(root);
cout << endl;
}
//Standard in order travsersal
void Tree::inOrderTraversal(Node* node) const {
if (node != nullptr) {
inOrderTraversal(node->left);
cout << node->small << ", ";
inOrderTraversal(node->middle);
if (!node->large.empty()) {
cout << node->large << ", ";
}
inOrderTraversal(node->right);
}
}
//Remove implementation
void Tree::remove(const string& key) {
Node* delNode=nullptr;
if (!search(key)) {
cout<<"not found"<<endl;
return;
}
else{
delNode = searchDeleteNode(root,key);
if(delNode){
remove(delNode, key);
}
}
}
void Tree::remove(Node* curr, const string& key) {
//删除非叶节点
//前驱替代
if(!curr->isLeaf()){
Node* pre = getPre(root,key);
string prev;
if(pre->isFull()){
prev = pre->large;
pre->large = key;
}else{
prev = pre->small;
pre->small = key;
}
if(curr->small == key){
curr->small = prev;
}else{
curr->large = prev;
}
remove(pre, key);
}
//删除叶节点
else{
//3节点直接删除
if(curr->isFull()){
if(key == curr->small){
curr->small = curr->large;
curr->large="";
}else{
curr->large="";
}
return;
}
//删除2节点
else{
//找兄弟借
if(curr->parent->left->hasKey(key)&&curr->parent->middle->isFull()){
curr->small = curr->parent->small;
curr->parent->small = curr->parent->middle->small;
curr->parent->middle->small = curr->parent->middle->large;
curr->parent->middle->large = "";
}
else if(curr->parent->middle->hasKey(key)&&curr->parent->left->isFull()){
curr->small = curr->parent->small;
curr->parent->small = curr->parent->left->large;
curr->parent->left->large = "";
}
else if(curr->parent->middle->hasKey(key)&&curr->parent->right->isFull()){
curr->small = curr->parent->large;
curr->parent->large = curr->parent->right->small;
curr->parent->right->small = curr->parent->right->large;
curr->parent->right->large = "";
}
else if(curr->parent->right && curr->parent->right->hasKey(key)&&curr->parent->middle->isFull()){
curr->small = curr->parent->large;
curr->parent->large = curr->parent->middle->large;
curr->parent->middle->large = "";
}
//兄弟都是2节点,找父亲借
else if(curr->parent->isFull()){
if(curr->parent->left->hasKey(key)){
curr->parent->middle->large = curr->parent->middle->small;
curr->parent->middle->small = curr->parent->small;
curr->parent->small = curr->parent->large;
curr->parent->large = "";
curr->parent->left = curr->parent->middle;
curr->parent->middle = curr->parent->right;
curr->parent->right = nullptr;
delete curr;
}
else if(curr->parent->middle->hasKey(key)){
curr->parent->left->large = curr->parent->small;
curr->parent->middle->small = curr->parent->small;
curr->parent->small = curr->parent->large;
curr->parent->large = "";
curr->parent->middle = curr->parent->right;
curr->parent->right = nullptr;
delete curr;
}
else if(curr->parent->right->hasKey(key)){
curr->parent->middle->large = curr->parent->large;
curr->parent->large = "";
curr->parent->right = nullptr;
delete curr;
}
}
//父兄都是2节点
else{
//删左边
if(curr->parent->left->hasKey(key)){
curr->small = curr->parent->small;
curr->large = curr->parent->middle->small;
delete curr->parent->middle;
curr->parent->middle = nullptr;
remove(curr->parent);
}
//删右边
if(curr->parent->middle->hasKey(key)){
curr->small = curr->parent->left->small;
curr->large = curr->parent->small;
curr->parent->left = curr;
curr->parent->right = nullptr;
remove(curr->parent);
}
}
}
}
}
//父兄均不可借的情况
void Tree::remove(Node* curr){
if(curr==nullptr)
return;
if(!curr->parent){
root = curr->left;
return;
}
//父不可借
if(!curr->parent->isFull()){
//兄弟可借
if(curr->parent->left == curr && curr->parent->middle->isFull()){
curr->small = curr->parent->small;
curr->parent->small = curr->parent->middle->small;
curr->parent->middle->small = curr->parent->middle->large;
curr->parent->middle->large = "";
curr->middle = curr->parent->middle->left;
curr->parent->middle->left = curr->parent->middle->middle;
curr->parent->middle->middle = curr->parent->middle->right;
curr->parent->middle->right = nullptr;
if(curr->middle)
curr->middle->parent = curr;
}
else if(curr->parent->middle == curr && curr->parent->left->isFull()){
curr->small = curr->parent->small;
curr->parent->small = curr->parent->left->large;
curr->parent->left->large = "";
curr->middle = curr->left;
curr->left = curr->parent->left->right;
curr->parent->left->right = nullptr;
}
//兄弟不可借
else{
//合并父和兄
//在左边
if(curr->parent->left == curr){
curr->small = curr->parent->small;
curr->large = curr->parent->middle->small;
curr->middle = curr->parent->middle->left;
curr->right = curr->parent->middle->middle;
curr->parent->left = curr;
if(curr->left)
curr->left->parent = curr;
if(curr->middle)
curr->middle->parent = curr;
if(curr->right)
curr->right->parent = curr;
delete curr->parent->middle;
curr->parent->middle = nullptr;
remove(curr->parent);
}
//在右边
else if(curr->parent->middle == curr){
curr->small = curr->parent->left->small;
curr->large = curr->parent->small;
curr->right = curr->left;
curr->left = curr->parent->left->left;
curr->middle = curr->parent->left->middle;
//更改父母
curr->left->parent = curr;
curr->middle->parent = curr;
curr->right->parent = curr;
delete curr->parent->left;
curr->parent->left = curr;
curr->parent->middle = nullptr;
remove(curr->parent);
}
}
}
//父可借
else{
//如果兄弟可借
if(curr->parent->left == curr && curr->parent->middle->isFull()){
curr->small = curr->parent->small;
curr->parent->small = curr->parent->middle->small;
curr->middle = curr->parent->middle->left;
//更改父母
curr->middle->parent = curr;
curr->parent->middle->small = curr->parent->middle->large;
curr->parent->middle->large = "";
curr->parent->middle->left = curr->parent->middle->middle;
curr->parent->middle->middle = curr->parent->middle->right;
curr->parent->middle->right = nullptr;
}
else if(curr->parent->middle == curr && curr->parent->left->isFull()){
curr->small = curr->parent->small;
curr->parent->small = curr->parent->left->large;
curr->middle = curr->left;
curr->left = curr->parent->left->right;
//更改父母
curr->left->parent = curr;
curr->parent->left->large = "";
curr->parent->left->right = nullptr;
}
else if(curr->parent->middle == curr && curr->parent->right->isFull()){
curr->small = curr->parent->large;
curr->parent->large = curr->parent->right->small;
curr->middle = curr->parent->right->left;
//更改父母
curr->middle->parent = curr;
curr->parent->right->left = curr->parent->right->middle;
curr->parent->right->middle = curr->parent->right->right;
curr->parent->right->small= curr->parent->right->large;
curr->parent->right->large = "";
curr->parent->right->right = nullptr;
}
else if(curr->parent->right == curr && curr->parent->middle->isFull()){
curr->small = curr->parent->large;
curr->parent->large = curr->parent->middle->large;
curr->middle = curr->left;
curr->left = curr->parent->middle->right;
//更改父母
curr->left->parent = curr;
curr->parent->middle->large = "";
curr->parent->middle->right = nullptr;
}
//兄弟不可借
else{
if(curr->parent->left == curr){
curr->small = curr->parent->small;
curr->large = curr->parent->middle->small;
curr->middle = curr->parent->middle->left;
curr->right = curr->parent->middle->middle;
//更改父母
curr->middle->parent = curr;
curr->right->parent = curr;
curr->parent->small = curr->parent->large;
curr->parent->large = "";
delete curr->parent->middle;
curr->parent->middle = curr->parent->right;
curr->parent->right = nullptr;
}
else if(curr->parent->middle == curr){
curr->large = curr->parent->small;
curr->small = curr->parent->left->small;
curr->right = curr->left;
curr->middle = curr->parent->left->middle;//
curr->left = curr->parent->left->left;//
//更改父母
curr->middle->parent = curr;
curr->left->parent = curr;
curr->parent->small = curr->parent->large;
curr->parent->large = "";
curr->parent->middle = curr->parent->right;
delete curr->parent->left;
curr->parent->left = curr;
curr->parent->right = nullptr;
}
else{
curr->large = curr->parent->large;
curr->small = curr->parent->middle->small;
curr->right = curr->left;
curr->middle = curr->parent->middle->middle;//
curr->left = curr->parent->middle->left;//
//更改父母
curr->middle->parent = curr;
curr->left->parent = curr;
delete curr->parent->middle;
curr->parent->middle = curr;
curr->parent->right = nullptr;
curr->parent->large = "";
}
}
}
}
//记录中序遍历结果 用来找前驱
void Tree::inOrderTraversal2(Node* node) const {
if (node != nullptr) {
inOrderTraversal2(node->left);
inorder[i++] = node->small;
inOrderTraversal2(node->middle);
if (!node->large.empty()) {
inorder[i++] = node->large;
}
inOrderTraversal2(node->right);
}
}
//通过中序遍历查找前驱节点
Node* Tree::getPre(Node* node,const string& key){
inOrderTraversal2(node);
int k = 0;
while(inorder[k]!=key)
k++;
string prev = inorder[k-1];
i=0;
return searchDeleteNode(root, prev);
}
Node* Tree::getRoot(){
return root;
}
//调整parent
void Tree::adjust(Node* node) const {
if (node != nullptr) {
if(node->left)
node->left->parent = node;
if(node->middle)
node->middle->parent = node;
if(node->right)
node->right->parent = node;
adjust(node->left);
if (!node->large.empty()) {
if(node->left)
node->left->parent = node;
if(node->middle)
node->middle->parent = node;
if(node->right)
node->right->parent = node;
}
adjust(node->middle);
adjust(node->right);
}
}