面試--二叉搜索樹的常見添加刪除前繼後繼

#include<iostream>
#include<vector>
#include<queue>
#include<string>
#include<stack>
using namespace std;

/*
    二叉搜索樹比二叉樹多一個性質,左節點的值小於父節點的值,右節點的值大於等於父節點的值
	二叉搜索樹右能夠排序,平衡二叉搜索樹有紅黑樹,AVL樹,此處僅是通常二叉搜索樹。
	二叉搜索樹一般設計比通常二叉樹多一個父節點域,不然要反覆找出某個節點的父節點
*/


struct Node
{
	int key;
	Node* left;
	Node* right;
	Node* parent;
	Node(int a)
	{
		key = a;
	   left = right=parent=nullptr;
	}

	///爲了代碼簡潔,此處二叉樹節點比較僅僅比較值是否相等
	bool operator==(Node * other)
	{
		return key == other->key;
	}

	bool operator!=(Node* other)
	{
		return key != other->key;
	}

};

///返回以p爲樹根的樹中最大節點
Node* maxNode(Node* p)
{
	if (p->right != nullptr)
	{
		while (p->right)
		{
			p = p->right;
		}
	}
	return p;
}

///返回以p爲樹根的樹中最小節點
Node* minNode(Node* p)
{
	if (p->left != nullptr)
	{
		while (p->left)
		{
			p = p->left;
		}
	}
	return p;
}

/*
返回節點p的後繼若不存在返回nullptr
*/
Node* successor(Node* root, Node* p)
{
	Node* result = nullptr;
	if (p->right != nullptr)
	{
		result = minNode(p->right);
	}
	else
	{
		while (p->parent!=nullptr&&p->parent->right == p)
		{
			p = p->parent;
		}
		if (p->parent != nullptr)
		{
			result = p->parent;
		}
	}
	return result;
}

Node* pressor(Node* root, Node* p)
{
	Node* result = nullptr;
	if (p->left != nullptr)
	{
		result = maxNode(p->left);
	}
	else
	{
		while (p->parent != nullptr&&p->parent->left == p)
		{
			p = p->parent;
		}
		if (p->parent != nullptr)
		{
			result = p->parent;
		}
	}
	return result;
}


Node* insertNode(Node* root, int k)
{
	if (root == nullptr)
	{
		root = new Node(k);
		return root;
	}
	else
	{
		Node* p=root,*q = root;
		Node*temp = new Node(k);
		while (p)
		{
			if (k < p->key)
			{
				q = p;
				p = p->left;
			}
			else
			{
				q = p;
				p = p->right;
			}
		}
		if (k < q->key)
		{
			q->left = temp;
			temp->parent = q;
		}
		else
		{
			q->right = temp;
			temp->parent = q;
		}
	}
	return root;
}

/*
找出一個節點的值等於k
*/
Node* searchNode(Node* root, int k)
{
	Node* p = root;
	while (p)
	{
		if (p->key == k)
		{
			return p;
		}
		else if (k < p->key)
		{
			p = p->left;
		}
		else
		{
			p = p->right;
		}
	}
	return p;
}

Node* deleteNode(Node* root, Node* p)
{
	if (root == nullptr||p==nullptr)return root;
	if (p->left == nullptr || p->right == nullptr)
	{
		if (p->left != nullptr)
		{
			Node* temp = p->left;
			temp->parent = p->parent;
			if (p->parent != nullptr) ///p不是根節點
			{
				if (p->parent->left == p)
					p->parent->left = temp;
				else
					p->parent->right = temp;
			}
			else    ///p是根節點
			{
				root = temp;
			}
			delete p;
			p = nullptr;
		}
		else if (p->right != nullptr)
		{
			Node* temp = p->right;
			temp->parent = p->parent;
			if (p->parent != nullptr)
			{
				if (p->parent->left == p)
					p->parent->left = temp;
				else
					p->parent->right = temp;
			}
			else
			{
				root = temp;
			}
			delete p;
			p = nullptr;
		}
		else
		{
			if (p ->parent== nullptr)
				root = nullptr;
			else
			{
				if (p->parent->left == p)
					p->parent->left = nullptr;
				else
					p->parent->right = nullptr;
			}
			delete p;
			p = nullptr;
		}
	}
	else   ///p的兩個孩子都不爲空
	{
		Node* temp = minNode(p->right);
		p->key = temp->key;
		///此時temp的左孩子確定爲nullptr,
		if (temp->right != nullptr)
		{
			temp->right->parent = temp->parent;
			if (temp->parent->left == temp)
				temp->parent->left = temp->right;
			else
				temp->parent->right = temp->right;
		}
		else
		{
			if (temp->parent->right == temp)
				temp->parent->right = nullptr;
			else 
				temp->parent->left = nullptr;
		}
		delete temp;
	}
	return root;
}

/*
刪除全部值爲k的節點
*/
Node* deleteNode(Node* root, int k)
{
	Node* p = searchNode(root, k);
	
	while (p!=nullptr&&p->key==k)
	{
		root=deleteNode(root, p);
		////這裏犯了一個錯誤,查找了半天還一直覺得刪除節點出了問題,指針果真nb
		///通過上一步指針p指向的空間已經被刪除了,因此下一步尋找p的後繼會出錯。
		p = searchNode(root,k);
	}
	
	return root;
}



Node* buildTree(int a[], int n)
{
	Node* root = nullptr;
	for (int i = 0; i < n; i++)
	{
		root = insertNode(root, a[i]);
	}
	return root;
}

void tree_sort(Node* root)
{
	if (root == nullptr)return;
	Node* p = minNode(root);
	while (p != nullptr)
	{
		cout << p->key << " ";
		p = successor(root, p);
	}
	cout << endl;
	
	p = maxNode(root);
	while (p != nullptr)
	{
		cout << p->key << " ";
		p = pressor(root, p);
	}
	cout << endl;
	
}


void levelOrder3(Node* p)
{
	if (p == nullptr)return;
	queue<Node*>qu;
	qu.push(p);
	while (!qu.empty())
	{
		p = qu.front();
		cout << p->key << " ";
		qu.pop();
		if (p->left != nullptr)
		{
			qu.push(p->left);
		}
		if (p->right != nullptr)
		{
			qu.push(p->right);
		}
	}
}

/*
int main()
{
	const int len = 30;
	int a[len];
	srand(1);
	for (int i = 0; i < len; i++)
	{
		a[i] = rand() % 30;
		if (a[i] == 0)a[i] += 1;
	}
	a[0] = 15;
	cout << endl << "=======數組a=====" << endl;
	for (int i = 0; i < len; i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;

	Node* root=buildTree(a, len);
	cout << endl << "=======逐層遍歷=====" << endl;
	levelOrder3(root);
	cout << endl<<"=======排序====="<<endl;
	tree_sort(root);
	cout << endl;
	while (true)
	{
		int m;
		cin >> m;
		root = deleteNode(root, m);
		cout << endl << "=======逐層=====" << endl;
		levelOrder3(root);
		cout << endl;
		cout << endl << "=======排序=====" << endl;
		tree_sort(root);
	}
}
*/
相關文章
相關標籤/搜索