Jelajahi Sumber

fixed the height function and the way I updated height (the whole tree is not updated) working on fixing getBalance which might require a balance_ variable for the nodes and moving where/how the rotations are done

Natalie Pueyo 8 tahun lalu
induk
melakukan
c9f3bfa268
3 mengubah file dengan 122 tambahan dan 19 penghapusan
  1. 103 9
      program3/AVLCommands.cpp
  2. 2 4
      program3/AVLCommands.h
  3. 17 6
      program3/test.cpp

+ 103 - 9
program3/AVLCommands.cpp

@@ -1,3 +1,6 @@
+// balance and height functions based on code from
+// http://www.sanfoundry.com/cpp-program-implement-avl-trees/
+
 #include <cassert>
 #include <iostream>
 #include <string>
@@ -66,15 +69,65 @@ int AVLCommands::max(int a, int b) {
 }
 
 int AVLCommands::height(std::shared_ptr<BSTNode> currentNode) {
-	if (currentNode == nullptr)
-      return 0;
+	if (root_ == nullptr) {
+		return 0;
+	}
+	int leftHeight, rightHeight, heightMax;
+
+	if (currentNode != nullptr) {
+		if (currentNode->left_ != nullptr) {
+			leftHeight = height(currentNode->left_);
+		} else {
+			leftHeight = 0;
+		}
+
+		if (currentNode->right_ != nullptr) {
+			rightHeight = height(currentNode->right_);
+		} else {
+			rightHeight = 0;
+		}
+
+		heightMax = 1 + max(leftHeight, rightHeight);
+		currentNode->height_ = heightMax;
+	}
   return currentNode->height_;
 }
 
 int AVLCommands::getBalance(std::shared_ptr<BSTNode> currentNode) {
-	if (currentNode == nullptr)
-      return 0;
-  return height(currentNode->left_) - height(currentNode->right_);
+	if (root_ == nullptr) {
+		return 0;
+	}
+	int leftHeight  = 0;
+	int rightHeight = 0;
+	int balanceFactor = 0;
+	if (currentNode->left_ != nullptr) {
+		leftHeight = currentNode->left_->height_;
+	}
+	if (currentNode->right_ != nullptr) {
+		rightHeight = currentNode->right_->height_;
+	}
+  balanceFactor = leftHeight - rightHeight);
+
+	// Left Left Case
+  if (lastNodeBalance > 1 && key < lastNode->left_->key_)
+      rightRotate(lastNode);
+
+  // Right Right Case
+  if (lastNodeBalance < -1 && key > lastNode->right_->key_)
+      leftRotate(lastNode);
+
+  // Left Right Case
+  if (lastNodeBalance > 1 && key > lastNode->left_->key_) {
+      lastNode->left_ =  leftRotate(lastNode->left_);
+      rightRotate(lastNode);
+  }
+
+  // Right Left Case
+  if (lastNodeBalance < -1 && key < lastNode->right_->key_) {
+      lastNode->right_ = rightRotate(lastNode->right_);
+      leftRotate(lastNode);
+  }
+	return 0;
 }
 
 std::shared_ptr<BSTNode> AVLCommands::rightRotate(std::shared_ptr<BSTNode> currentNode){
@@ -109,7 +162,30 @@ std::shared_ptr<BSTNode> AVLCommands::leftRotate(std::shared_ptr<BSTNode> curren
   return y;
 }
 
+void AVLCommands::printTree(){
+	printTree(root_);
+}
+
+void AVLCommands::printTree(std::shared_ptr<BSTNode> currentNode){
+	if (root_ == nullptr) {
+		std::cout << "tree is empty" << std::endl;
+		return;
+	} else {
+		std::cout << "key: " << currentNode->key_ << std::endl;
+		std::cout << "height: " << currentNode->height_ << std::endl;
+		if (currentNode->left_ != nullptr) {
+			std::cout << "left" << std::endl;
+			printTree(currentNode->left_);
+		}
+		if (currentNode->right_ != nullptr) {
+			std::cout << "right" << std::endl;
+			printTree(currentNode->right_);
+		}
+	}
+}
+
 void AVLCommands::Insert(int key) {
+	std::cout << "Inserting new key: " << key << std::endl;
 	// BST insertion
 	if (root_ == nullptr) {
 		root_ = std::make_shared<BSTNode>(key);
@@ -129,9 +205,26 @@ void AVLCommands::Insert(int key) {
 	}
 	size_++;
 
-	// Update hight of this ancestor's node... need to check if this should be currNode or lastNode
+	// update height of the tree
+	height(root_);
+
 	std::cout << "insert height update attempt..." << std::endl;
-	lastNode->height_ = 1 + max(height(lastNode->left_), height(lastNode->right_));
+	int leftHeight, rightHeight;
+
+	if (lastNode->left_ != nullptr) {
+		leftHeight = lastNode->left_->height_;
+	} else {
+		leftHeight = 0;
+	}
+
+	if (lastNode->right_ != nullptr) {
+		rightHeight = lastNode->right_->height_;
+	} else {
+		rightHeight = 0;
+	}
+
+	lastNode->height_ = 1 + max(leftHeight, rightHeight);
+
 	std::cout << "New height: " << lastNode->height_ << std::endl;
 	std::cout << "insert height update attempt success!" << std::endl;
 
@@ -161,6 +254,7 @@ void AVLCommands::Insert(int key) {
       lastNode->right_ = rightRotate(lastNode->right_);
       leftRotate(lastNode);
   }
+
 }
 
 bool AVLCommands::Delete(int key) {
@@ -306,8 +400,8 @@ std::string AVLCommands::JSON() const {
 			auto v = nodes.front();
 			nodes.pop();
 			std::string key = std::to_string(v->key_);
-			std::string height = std::to_string(v->height_);
-			result[key]["height"] = height;
+			//std::string height = std::to_string(v->height_);
+			//result[key]["height"] = height;
 			result[key]["left"] = v->left_->key_;
 			if (v->left_ != nullptr) {
 				result[key]["left"] = v->left_->key_;

+ 2 - 4
program3/AVLCommands.h

@@ -40,10 +40,7 @@ class AVLCommands {
  	size_t size() const;
  	bool empty() const;
  	int DeleteMin();
-  // add int getParent(); int getLeft(); int getRight();
-  int getParent(int key);
-  int getLeft(int key);
-  int getRight(int key);
+  void printTree();
 
  private:
   int max(int a, int b);
@@ -53,6 +50,7 @@ class AVLCommands {
   std::shared_ptr<BSTNode> leftRotate(std::shared_ptr<BSTNode>);
   void DeleteLeaf(std::shared_ptr<BSTNode> currentNode);
   int DeleteMin(std::shared_ptr<BSTNode> currentNode);
+  void printTree(std::shared_ptr<BSTNode> currentNode);
 
  	std::shared_ptr<BSTNode> root_;
  	size_t size_;

+ 17 - 6
program3/test.cpp

@@ -4,14 +4,25 @@
 int main()
 {
     AVLCommands avl;
-    avl.Insert(3);
-    avl.Insert(50);
     avl.Insert(1);
-    avl.Insert(15);
+    avl.printTree();
     avl.Insert(2);
+    avl.printTree();
+    avl.Insert(3);
+    avl.printTree();
+    avl.Insert(4);
+    avl.printTree();
     avl.Insert(5);
-    avl.Insert(20);
-    avl.Insert(50);
-    avl.Delete(15);
+    avl.printTree();
+    avl.Insert(6);
+    avl.printTree();
+    avl.Insert(7);
+    avl.printTree();
+    avl.Insert(8);
+    avl.printTree();
+    avl.Insert(9);
+    //avl.Insert(50);
+    avl.printTree();
+    //avl.Delete(15);
     return 0;
 }