二叉搜尋樹建立、插入、刪除、前繼節點、後繼節點之c++實現
阿新 • • 發佈:2019-02-11
程式碼執行結果:#include "stdafx.h" #include <string> #include <stdlib.h> #include <iostream> using namespace std; typedef struct Node { int key; //鍵值 struct Node *left; //左節點 struct Node *right; //右節點 struct Node *father; //父節點 int times; //節點出現的次數 } Node, *pNode; void creatBinarySearchTree(pNode &pBSTTree, int *ptr, int len); void insertNode(pNode &pBSTTree, int value); void mallocInitNode(pNode &pInsertNode, int value); pNode findMinNode(pNode &pTree); pNode findMaxNode(pNode &pTree); pNode findPredecessor(pNode &pSearchNode); pNode findSuccessor(pNode &pSearchNode); void deleteNode(pNode& pdeleteNode); void changeFatherChildNode(pNode& pdeleteNode, pNode& pNewChildNode); int main() { int a[] = {15,15, 6, 18, 3, 7, 17, 20, 2, 4, 13, 9}; int len = sizeof(a) / sizeof(int); pNode pBSTTree = NULL; pNode pPreNode = NULL; pNode pSuccessor = NULL; /* 建立二叉查詢樹 */ creatBinarySearchTree(pBSTTree, a, len); /* 尋找二叉查詢樹中的最大值 */ cout << "最小值的節點為:" << findMinNode(pBSTTree)->key << endl; cout << "最大值的節點為:" << findMaxNode(pBSTTree)->key << endl; /* 尋找某個節點的前驅節點 */ pPreNode = findPredecessor(pBSTTree->left->right); if (NULL != pPreNode) { cout << "該節點的前驅節點為:" << pPreNode->key << endl; } else { cout << "該節點無前驅節點" << endl; } /* 尋找某個節點的後繼節點 */ pSuccessor = findSuccessor(pBSTTree->left->left->left); if (NULL != pPreNode) { cout << "該節點的後繼節點為:" << pSuccessor->key << endl; } else { cout << "該節點無後繼節點" << endl; } /* 刪除某個節點 */ deleteNode(pBSTTree->right->right); deleteNode(pBSTTree->left->left); cout << "最小值的節點為:" << findMinNode(pBSTTree)->key << endl; pSuccessor = findSuccessor(pBSTTree->left->left); if (NULL != pPreNode) { cout << "該節點的後繼節點為:" << pSuccessor->key << endl; } else { cout << "該節點無後繼節點" << endl; } free(pBSTTree); pBSTTree = NULL; return 0; } /* 建立一個二叉查詢樹 */ void creatBinarySearchTree(pNode &pBSTTree, int *ptr, int len) { for (int i = 0; i < len; i++) { insertNode(pBSTTree, *(ptr + i)); } } /* 插入一個節點,複雜度為O(nlogn) */ void insertNode(pNode &pBSTTree, int value) { pNode pInsertNode; /* 第一個節點,直接插入 */ if (NULL == pBSTTree) { mallocInitNode(pInsertNode, value); pBSTTree = pInsertNode; return; } /* 如果鍵值已經存在的話,只需要times++ */ if (value == pBSTTree->key) { pBSTTree->times++; return; } /* 如果小於本節點的值,且該節點無左孩子 */ if ((NULL == pBSTTree->left) && (value < pBSTTree->key)) { mallocInitNode(pInsertNode, value); pInsertNode->father = pBSTTree; pBSTTree->left = pInsertNode; return; } /* 如果大於本節點的值,且該節點無右孩子 */ if ((NULL == pBSTTree->right) && (value > pBSTTree->key)) { mallocInitNode(pInsertNode, value); pInsertNode->father = pBSTTree; pBSTTree->right = pInsertNode; return; } /* 如果小於本節點的值,但是該節點已經有左孩子,那麼就繼續遞迴 */ if ((NULL != pBSTTree->left) && (value < pBSTTree->key)) { insertNode(pBSTTree->left, value); } /* 如果大於本節點的值,但是該節點已經有右孩子,那麼就繼續遞迴 */ if ((NULL != pBSTTree->right) && (value > pBSTTree->key)) { insertNode(pBSTTree->right, value); } } /* 建立新節點並初始化 */ void mallocInitNode(pNode &pInsertNode, int value) { pInsertNode = (pNode)malloc(sizeof(Node)); pInsertNode->key = value; pInsertNode->father = NULL; pInsertNode->left = NULL; pInsertNode->right = NULL; pInsertNode->times = 1; } /* 尋找二叉樹中最小的節點和最大的節點 */ pNode findMinNode(pNode &pTree) { pNode pTemp = pTree; while (NULL != pTemp->left) { pTemp = pTemp->left; } return pTemp; } pNode findMaxNode(pNode &pTree) { pNode pTemp = pTree; while (NULL != pTemp->right) { pTemp = pTemp->right; } return pTemp; } /* 找出前驅節點 */ pNode findPredecessor(pNode &pSearchNode) { /* 如果左子樹存在的話,則返回左子樹中最大的節點,即為比它小的之中的最大的節點 */ if (NULL != pSearchNode->left) { return findMaxNode(pSearchNode->left); } /* 如果左子樹不存在的話,則需要往上找,直到找到目標節點是目標節點父親節點的右孩子 */ pNode pTemp = pSearchNode; while(pTemp != pTemp->father->right) { pTemp = pTemp->father; } return pTemp->father; } /* 找出後繼節點 */ pNode findSuccessor(pNode &pSearchNode) { /* 如果右子樹存在的話,則返回右子樹中最小的節點,即為比它大的之中的最小的節點 */ if (NULL != pSearchNode->right) { return findMinNode(pSearchNode->right); } /* 如果左子樹不存在的話,則需要往上找,直到找到目標節點是目標節點父親節點的右孩子 */ pNode pTemp = pSearchNode; while(pTemp != pTemp->father->left) { pTemp = pTemp->father; } return pTemp->father; } void deleteNode(pNode& pdeleteNode) { /* 1.判斷該節點的個數,如果節點的個數大於或等於1,則直接將該節點的個數-1 */ if (1 < pdeleteNode->times) { pdeleteNode->times--; return; } /* 2.如果該節點只有一個,那麼考慮刪除 */ /* 2.1 如果該節點沒有孩子,則直接刪除 */ pNode pTemp = NULL; if ((NULL == pdeleteNode->left) && (NULL == pdeleteNode->right)) { changeFatherChildNode(pdeleteNode, pTemp); } /* 2.2 如果該節點只有一個孩子,那麼直接用該孩子代替該節點 */ else if ((NULL == pdeleteNode->left) && (NULL != pdeleteNode->right)) { changeFatherChildNode(pdeleteNode, pdeleteNode->right); } else if ((NULL == pdeleteNode->right) && (NULL != pdeleteNode->left)) { changeFatherChildNode(pdeleteNode, pdeleteNode->left); } /* 2.3 如果該節點有兩個孩子,那麼考慮用該節點的前驅或者後繼來代替該節點。在此,我們選擇用前驅代替該節點 */ else { pTemp = findPredecessor(pdeleteNode); pNode pRightChild = pdeleteNode->right; changeFatherChildNode(pdeleteNode, pTemp); pTemp->right = pRightChild; } } void changeFatherChildNode(pNode& pdeleteNode, pNode& pNewChildNode) { if (pdeleteNode == pdeleteNode->father->right) { pdeleteNode->father->right = pNewChildNode; } else { pdeleteNode->father->left = pNewChildNode; } }