我正在写一个BST,从7开始向它添加0到15的数字。
然后,当我尝试将它们从0删除到15时,当我尝试删除节点9时,我的getLeftChildHeight()
会在EXC_BAD_ACCESS
行上抛出if (left == NULL)
。
为什么我无法检查指针是否为NULL,这是怎么回事?
#include <iostream>
#include <stdio.h>
#include <queue>
#include <stack>
using namespace std;
typedef unsigned long long int KType;
struct Node {
KType key;
Node* left;
Node* right;
Node* parent;
int level; // from root to node; depth(root) = 0
int height; // from node to leaf; height(leaf) = 0
int sub_tree_size; // the size of the subtree; size(leaf) = 1
Node(): key(0), left(NULL), right(NULL),
parent(NULL), level(0), height(0), sub_tree_size(0) {}
Node(const KType& _key): key(_key), left(NULL), right(NULL),
parent(NULL), level(0), height(0),
sub_tree_size(1) {}
~Node() { delete left; delete right; }
friend ostream& operator << (ostream& os, const Node* nb);
/*
* Returns the height of the left node
*/
int getLeftChildHeight() {
if (left == NULL)
return -1;
else
return left -> height;
}
/*
* Returns the height of the right node
*/
int getRightChildHeight() {
if (right == NULL)
return -1;
else
return right -> height;
}
/*
* Returns the height of the higher child
*/
int getMaxLRHeight() {
return std::max (getLeftChildHeight(), getRightChildHeight());
}
/*
* Returns the height of the lower child
*/
int getMinLRHeight() {
return std::min (getLeftChildHeight(), getRightChildHeight());
}
/*
* Returns the difference between the heights of the children
*/
int getDeltaHeight() {
return abs(getRightChildHeight() - getLeftChildHeight());
}
/*
* Prints all the node properties
*/
void print() {
printf ("| (%llu) ", key);
printf ("H: %d ", height);
printf ("L: %d ", level);
//printf("S: %d ", sub_tree_size);
printf("|");
}
};
// Standard output operator overload
ostream& operator << (ostream& os, const Node* n) {
cout << n -> key << " ";
return os;
}
struct BST {
int nNodes;
Node* root;
~BST() { nNodes = 0; delete root; }
/**
* Adds a new node and updates all the proberties up to the root
*/
void add(const KType& key) {
nNodes++;
Node* back = NULL;
if (root == NULL)
root = new Node(key);
else {
Node* v = root;
while(v != NULL) {
v -> sub_tree_size++;
if (key <= v -> key)
if (v -> left != NULL)
v = v -> left;
else {
v -> left = new Node(key);
v -> left -> level = v -> level + 1;
v -> left -> parent = v;
back = v -> left;
v = NULL;
}
else
if (v -> right != NULL)
v = v -> right;
else {
v -> right = new Node(key);
v -> right -> level = v -> level + 1;
v -> right -> parent = v;
back = v -> right;
v = NULL;
}
}
while (back != NULL) {
back -> height = back -> getMaxLRHeight() + 1;
back = back -> parent;
}
}
}
/**
* Prints the tree
*/
void printTree(bool full_info = false) {
if (nNodes == 0) {
cout << "The tree is empty!\n";
return;
}
printf("Number of nodes: %d\n", nNodes);
queue<Node*> q;
Node* v = root;
q.push(v);
int level = 0;
while (!q.empty()) {
v = q.front();
q.pop();
if (v -> level > level) {
level = v -> level;
printf("\n");
}
if (full_info)
v->print();
else
cout << v;
if (v -> left != NULL)
q.push(v -> left);
if (v -> right != NULL)
q.push(v -> right);
}
cout << "\n--------------------\n";
}
/*
* Reads the tree from the standard input
*/
void getTree() {
int n = 0;
KType k;
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%llu", &k);
add(k);
}
}
/*
* Returns the pointer to the node if the tree contains the key
*/
Node* find(const KType& k) {
if (root == NULL) return NULL;
Node* v = root;
while (v != NULL) {
if (v -> key == k) return v;
if (k < v -> key)
v = v -> left;
else
v = v -> right;
}
return v;
}
/*
* Returns true if the tree contains the key
*/
bool contains(const KType& k) {
return find(k) != NULL;
}
/*
* Returns the pointer to the minimum for the subtree with the local_root,
* which is the leftmost node in the subtree
*/
Node* min(Node* local_root) {
Node* v = local_root;
while (v -> left != NULL)
v = v -> left;
return v;
}
/*
* Returns the minimum key for the subtree with the local_root,
* which is the leftmost key in the subtree
*/
KType minKey(Node* local_root) {
return min(local_root) -> key;
}
/*
* Returns the minimum key for the subtree with the k as its root,
* which is the leftmost key in the subtree
*/
KType minKey(const KType& k) {
Node *v = find(k);
return min(v) -> key;
}
/*
* Returns the pointer to the maximum for the subtree with the local_root,
* which is the rightmost node in the subtree
*/
Node* max(Node* local_root) {
Node* v = local_root;
while (v -> right != NULL)
v = v -> right;
return v;
}
/*
* Returns the maximum key for the subtree with the local_root
* which is the rightmost key in the subtree
*/
KType maxKey(Node* local_root) {
return max(local_root) -> key;
}
/*
* Returns the maximum key for the subtree with the k as its root
* which is the rightmost key in the tree
*/
KType maxKey(const KType& k) {
Node *v = find(k);
return max(v) -> key;
}
/*
* Returns the pointer to the predecessor of the node
*/
Node* predecessor(Node* node) {
if (node -> left == NULL) {
Node* start = node;
while (node -> key >= start -> key && node != root)
node = node -> parent;
if (node == root && node -> key > start -> key)
return start;
else
return node;
}
else
return max(node -> left);
}
/*
* Returns the pointer to the predecessor of the key k
*/
Node* predecessor(const KType& k) {
Node* node = find(k);
return predecessor(node);
}
/*
* Returns the pointer to the predecessor of the key k
*/
KType predecessorKey(const KType& k) {
Node* node = find(k);
return predecessor(node) -> key;
}
/*
* Returns the pointer to the successor of the node
*/
Node* successor(Node* node) {
if (node -> right == NULL) {
Node* start = node;
while (node -> key <= start -> key && node != root)
node = node -> parent;
if (node == root && node -> key < start -> key)
return start;
else
return node;
}
else
return min(node -> right);
}
/*
* Returns the pointer to the successor of the key k
*/
Node* successor(const KType& k) {
Node* node = find(k);
return successor(node);
}
/*
* Returns the pointer to the successor of key
*/
KType successorKey(const KType& k) {
Node* node = find(k);
return successor(node) -> key;
}
/*
* Returns the pointer to the right child if the node is
* the left child of its parent and vice versa
*/
Node* otherChild(Node* node) {
if (node == root) return NULL;
if (node -> parent -> left == NULL ||
node -> parent -> right == NULL)
return NULL;
if (node == node -> parent -> left)
return node -> parent -> right;
else
return node -> parent -> left;
}
/*
* Returns the key of the right child if the node is
* the left child of its parent and vice versa
*/
long long int otherChildKey(Node* node) {
Node *v = otherChild(node);
if (v == NULL)
return -1;
else
return v -> key;
}
/*
* Returns the key of the right child if the node is
* the left child of its parent and vice versa
*/
long long int otherChildKey(const KType& k) {
Node *v = otherChild(find(k));
if (v == NULL)
return -1;
else
return v -> key;
}
/*
* Returns the height of the other child
*/
int otherChildHeight(Node* node) {
Node *v = otherChild(node);
if (v == NULL)
return -1;
else
return v -> height;
}
/**
* Returns true if child is the left child of its parent
* and false otherwise
*/
bool isLeftChild(Node *child) {
if (child -> parent -> left != NULL &&
child -> parent -> left == child)
return true;
return false;
}
/**
* Returns true if the key k is the left child of its parent
* and false otherwise
*/
bool isLeftChild(const KType &k) {
Node* child = find(k);
if (child -> parent -> left != NULL &&
child -> parent -> left == child)
return true;
return false;
}
/**
* Returns true if child is the right child of its parents
* and false otherwise
*/
bool isRightChild(Node *child) {
if (child -> parent -> right != NULL &&
child -> parent -> right == child)
return true;
return false;
}
/**
* Returns true if the key k is the right child of its parent
* and false otherwise
*/
bool isRightChild(const KType &k) {
Node* child = find(k);
if (child -> parent -> right != NULL &&
child -> parent -> right == child)
return true;
return false;
}
/*
* Returns true if the node has only the right child
* and false otherwise
*/
bool hasOnlyRightChild (Node* node) {
return (node -> left == NULL && node -> right != NULL);
}
/*
* Returns true if the node has only the left childe
* and false otherwise
*/
bool hasOnlyLeftChild (Node* node) {
return (node -> right == NULL && node -> left != NULL);
}
/*
* Returns true if the node with the key k has only the right child
* and false otherwise
*/
bool hasOnlyRightChild (const KType& k) {
Node* node = find(k);
return (node -> left == NULL && node -> right != NULL);
}
/*
* Returns true if the node with the key k has only the left child
* and false otherwise
*/
bool hasOnlyLeftChild (const KType& k) {
Node* node = find(k);
return (node -> right == NULL && node -> left != NULL);
}
/*
* Deletes the leaf of the tree
*/
void deleteLeaf(Node * leaf) {
if (leaf -> left != NULL || leaf -> right != NULL) {
cout << "Not a leaf!!\n";
return;
}
nNodes--;
if (leaf == root) {
root = NULL;
delete root;
return;
};
// Deleting the node
Node* v = leaf -> parent;
if (isLeftChild(leaf)) {
leaf -> parent = NULL;
//delete leaf;
//v -> left -> parent = NULL;
//delete v -> left;
v -> left = NULL;
delete v -> left;
}
else {
leaf -> parent = NULL;
//delete leaf;
//v -> right -> parent = NULL;
//delete v -> right;
v -> right = NULL;
delete v -> left;
}
// Updating the parameters
while (v != NULL) {
v -> height = v -> getMaxLRHeight() + 1;
v -> sub_tree_size--;
v = v -> parent;
}
}
/*
* Deletes the leaf of the tree with the key k
*/
void deleteLeafKey(const KType& k) {
Node* leaf = find(k);
if (leaf == NULL) return;
if (leaf -> left != NULL || leaf -> right != NULL) {
cout << "Not a leaf!!\n";
return;
}
deleteLeaf(leaf);
}
/*
* Increments the level of all the nodes that are lifted up after the deletion
*/
void updLevelDown(Node* node) {
stack <Node*> s;
s.push(node);
while(!s.empty()) {
Node* v = s.top();
s.pop();
v -> level--;
if (v -> left != NULL)
s.push(v -> left);
if (v -> right != NULL)
s.push(v -> right);
}
}
/*
* Kills the node
*/
void killNode(Node* node) {
node -> left = NULL;
node -> right = NULL;
node -> parent = NULL;
delete node;
}
/*
* Deletes a node that has only one child
*/
void deleteOneChildNode(Node *node) {
Node* upd;
Node* upd2;
nNodes--;
if (node == root) {
upd = root;
if (root -> right != NULL)
root = root -> right;
else
root = root -> left;
updLevelDown(upd);
killNode(upd);
return;
}
// Deleting the node
if (isLeftChild(node)) {
if (hasOnlyLeftChild(node)) {
upd = node -> left;
node -> parent -> left = node -> left;
node -> left -> parent = node -> parent;
killNode(node);
}
else {
upd = node -> right;
node -> parent -> left = node -> right;
node -> right -> parent = node -> parent;
killNode(node);
}
}
else {
if (hasOnlyLeftChild(node)) {
upd = node -> left;
node -> parent -> right = node -> left;
node -> left -> parent = node -> parent;
killNode(node);
}
else {
upd = node -> right;
node -> parent -> right = node -> right;
node -> right -> parent = node -> parent;
killNode(node);
}
}
// Updating the parameters
upd2 = upd;
updLevelDown(upd2);
while (upd2 != NULL) {
upd -> height = upd -> getMaxLRHeight() + 1;
upd -> sub_tree_size--;
upd = upd -> parent;
}
}
/*
* Deletes a node that has both children
*/
void deleteOneChildNodeKey(const KType& k) {
Node* node = find(k);
deleteOneChildNode(node);
}
/*
* Returns true if the node is a leaf and false otherwise
*/
bool isLeaf(Node* node) {
return (node -> left == NULL && node -> right == NULL);
}
/*
* Returns true if the node has both children
*/
bool hasBothChildren(Node* node) {
return (node -> left != NULL && node ->right != NULL);
}
/*
* Returns true if the node has both children
*/
bool hasBothChildrenKey(const KType& k) {
Node* node = find(k);
return (node -> left != NULL && node ->right != NULL);
}
/*
* Swaps two keys
*/
void swapKeys(Node* nodeA, Node* nodeB) {
KType c = nodeA -> key;
nodeA -> key = nodeB -> key;
nodeB -> key = c;
}
// Deletes a node with two children
void deleteTwoChildrenNode(Node* node) {
Node* s = successor(node);
swapKeys(node, s);
if (isLeaf(s))
deleteLeaf(s);
else
deleteOneChildNode(s);
}
// Deletes a key with two children
void deleteTwoChildrenNodeKey(const KType& k) {
Node* node = find(k);
deleteTwoChildrenNode(node);
}
/*
* Deletes any node from the tree
*/
void deleteNode(Node* node) {
if (isLeaf(node))
deleteLeaf(node);
else
if (hasBothChildren(node))
deleteTwoChildrenNode(node);
else deleteOneChildNode(node);
}
/*
* Deletes any key from the tree
*/
void deleteNodeKey(const KType& k) {
Node* node = find(k);
if (node != NULL) deleteNode(node);
}
};
int main(int argc, const char * argv[]) {
string path = "/Users/alekscooper/Dropbox/Binary Search Tree/Input/";
path+= "input4.txt";
freopen (path.c_str(), "r", stdin);
BST t;
t.getTree();
t.printTree(1);
for(int i = 0; i < 17; i++)
t.deleteNodeKey(i);
t.printTree(1);
return 0;
}
这是input4.txt文件:
16
7
3
12
1
6
9
13
0
2
4
8
11
15
5
10
14
答案 0 :(得分:0)
两个错误:
1:
// Updating the parameters
upd2 = upd;
updLevelDown(upd2);
while (upd2 != NULL) {
upd -> height = upd -> getMaxLRHeight() + 1;
upd -> sub_tree_size--;
upd = upd -> parent;
}
}
您正在查看upd2
,但您正在更改upd
。因此,您一直运行到upd
为NULL
,然后在其上调用getMaxLRHeight
。
2:
struct BST {
int nNodes;
Node* root;
~BST() { nNodes = 0; delete root; }
....
你没有UPD的构造函数。所以它从不可预测的价值开始。添加:
BST() { nNodes = 0; root = NULL; }