实验7
学号: 姓名: 专业:
7.1实验目的
(1) 掌握顺序表的查找方法,尤其是二分查找方法。
(2) 掌握二叉排序树的建立及查找。
查找是软件设计中的最常用的运算,查找所涉及到的表结构的不同决定了查找的方法及其性能。二分查找是顺序表的查找中的最重要的方法,应能充分理解其实现方法和有关性能,并能借助其判定树结构来加深理解。二叉排序树结构在实验时具有一定的难度,可结合二叉树的有关内容和方法来实现。
7.2 实验任务
编写算法实现下列问题的求解。
(1) 对下列数据表,分别采用二分查找算法实现查找,给出查找过程依次所比较的元素(的下标),并以二分查找的判定树来解释。
第一组测试数据:
数据表为 (1,2,3,4,6,7,8,9,10,11,12,13,17,18,19,20,24,25,26,30,35,40,45,50,100)
查找的元素分别为: 2,8,20, 30,50,5,15,33,110
第二组数据:
数据表为 (2,3,5,7,8,10,12,15,18,20,22,25,30,35,40,45,50,55,60, 80,100)
查找的元素分别为: 22,8,80,3,100,1,13,120
(2) 设计出在二叉排序树中插入结点的算法,在此基础上实现构建二叉排序树的算法。
测试数据:构建二叉排序树的输入序列如下:
第一组数据:
100,150,120,50,70,60,80,170,180,160,110,30,40,35,175
第二组数据:
100,70,60,80,150,120,50,160,30,40,170,180,175,35
(3) 设计算法在二叉排序树中查找指定值的结点。
测试数据:在任务<1>中第一组测试数据所构造的二叉排序树中,分别查找下列元素: 150,70,160,190,10,55,175
(4) 设计算法在二叉排序树中删除特定值的结点。
测试数据:在任务(1)中第一组测试数据所构造的二叉排序树中,分别删除下列元素:30,150,100
(5) 已知整型数组A[1..26]递增有序,设计算法以构造一棵平衡的二叉排序树来存放该数组中的所有元素。
测试数据:数组元素分别为:
第一组数据:
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26)
第二组数据:
(1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210,231,253,277,302,328)
7.3实验数据要求
自我编写测试样例,要求每个功能函数的测试样例不少于两组
7.4 运行结果截图及说明
图1 测试(1)①
图2 测试(1)②
图3 测试(2)①
图4 测试(2)②
图5 测试(3)
图6 测试(4)
图7 测试(5)①
图8 测试(5)①
图9 测试(5)①
图10 测试(5)①
图11 测试(5)②
图12 测试(5)②
图13 测试(5)②
图14 测试(5)①(全)
图15 测试(5)②(全)
7.5 附源代码
二分查找:
1 // stdafx.h : include file for standard system include files, 2 // or project specific include files that are used frequently, but 3 // are changed infrequently 4 // 5 6 #if !defined(AFX_STDAFX_H__940FF418_5647_412A_8B4F_3C89C07F8CA5__INCLUDED_) 7 #define AFX_STDAFX_H__940FF418_5647_412A_8B4F_3C89C07F8CA5__INCLUDED_ 8 9 #if _MSC_VER > 100010 #pragma once11 #endif // _MSC_VER > 100012 13 14 #include15 16 using namespace std;17 18 typedef long elementType;19 20 const long maxn = 10000 + 3; 21 22 // TODO: reference additional headers your program requires here23 24 //{ {AFX_INSERT_LOCATION}}25 // Microsoft Visual C++ will insert additional declarations immediately before the previous line.26 27 #endif // !defined(AFX_STDAFX_H__940FF418_5647_412A_8B4F_3C89C07F8CA5__INCLUDED_)
1 // SeqList.h: interface for the SeqList class. 2 // 3 // 4 5 #if !defined(AFX_SEQLIST_H__58D90762_85EC_4BBB_94EA_068A582CCD81__INCLUDED_) 6 #define AFX_SEQLIST_H__58D90762_85EC_4BBB_94EA_068A582CCD81__INCLUDED_ 7 8 #if _MSC_VER > 1000 9 #pragma once10 #endif // _MSC_VER > 100011 12 class SeqList 13 {14 public:15 SeqList();16 virtual ~SeqList();17 bool seqListFull();18 bool seqListEmpty();19 void randomInsert( elementType number );20 void insert( elementType value );21 void showLength();22 elementType binarySearch( elementType value );23 friend ostream &operator<<( ostream &os, SeqList &SL )24 {25 if( SL.length == -1 )26 {27 return os;28 }29 int column = 0;30 for( int i = 1; i <= SL.length; i ++ )31 {32 os << setw(6) << setiosflags( ios::left ) << SL.Arr[i] << " ";33 column ++;34 if( column % 10 == 0 )35 os << endl;36 }37 os << endl;38 }39 40 private:41 elementType Arr[maxn];42 int length;43 44 };45 46 #endif // !defined(AFX_SEQLIST_H__58D90762_85EC_4BBB_94EA_068A582CCD81__INCLUDED_)
1 // SeqList.cpp: implementation of the SeqList class. 2 // 3 // 4 5 #include "stdafx.h" 6 #include "SeqList.h" 7 8 // 9 // Construction/Destruction 10 // 11 12 SeqList::SeqList() 13 { 14 length = 0; 15 } 16 17 SeqList::~SeqList() 18 { 19 ios::sync_with_stdio(false); 20 cout << "The SeqList destruction has been called!" << endl; 21 } 22 23 bool SeqList::seqListFull() 24 { 25 return length == maxn - 1; 26 } 27 28 bool SeqList::seqListEmpty() 29 { 30 return length == 0; 31 } 32 33 void SeqList::randomInsert( elementType number ) 34 { 35 ios::sync_with_stdio(false); 36 if( seqListFull() ) 37 { 38 cerr << "Inserting failed!The sequence list has been full.Error in void SeqList::randomInsert( int number )" << endl; 39 return; 40 } 41 42 srand( time(NULL) ); 43 elementType last = -999; 44 for( int i = 0; i < number; i ++ ) 45 { 46 elementType key = rand() % ( 10000 - 100 + 1 ) + 100; 47 if( key >= last ) 48 { 49 length ++; 50 Arr[length] = key; 51 last = key; 52 } 53 else 54 { 55 i --; 56 } 57 } 58 } 59 60 void SeqList::insert( elementType value ) 61 { 62 ios::sync_with_stdio(false); 63 if( seqListFull() ) 64 { 65 cerr << "Inerting failed!The sequence list has been full.Error in void SeqList::insert( elementType value )" << endl; 66 return; 67 } 68 69 length ++; 70 Arr[length] = value; 71 } 72 73 elementType SeqList::binarySearch( elementType value ) 74 { 75 ios::sync_with_stdio(false); 76 if( seqListEmpty() ) 77 { 78 cerr << "Searching failed!The sequence list is empty.Error in elementType SeqList::binarySearch( elementType value )" << endl; 79 return -1; 80 } 81 elementType lower = 0, upper = length; 82 while( lower <= upper ) 83 { 84 elementType mid = ( lower + upper ) >> 1; //+ 1; 85 if( Arr[mid] == value ) 86 { 87 return mid; 88 } 89 if( Arr[mid] >= value ) 90 { 91 upper = mid - 1; 92 } 93 else 94 { 95 lower = mid + 1; 96 } 97 } 98 return -1; 99 }100 101 void SeqList::showLength()102 {103 ios::sync_with_stdio(false);104 cout << length << endl;105 }
1 // BinarySearch.cpp : Defines the entry point for the console application. 2 // 3 4 #include "stdafx.h" 5 #include "SeqList.h" 6 7 void test1() 8 { 9 ios::sync_with_stdio(false);10 SeqList SL1;11 elementType number;12 cin >> number;13 SL1.randomInsert( number );14 cout << SL1;15 elementType value;16 for( int i = 0; i < number; i ++ )17 {18 cin >> value;19 if( SL1.binarySearch(value) != -1 )20 {21 cout << value << " is in the sequence list." << endl;22 }23 else24 {25 cout << value << " is not in the sequence list." << endl;26 }27 }28 }29 30 void test2()31 {32 ios::sync_with_stdio(false);33 SeqList SL1;34 elementType value;35 while( cin >> value )36 {37 if( value == -999 )38 {39 break;40 }41 SL1.insert(value);42 }43 SL1.showLength();44 cout << SL1;45 46 elementType key;47 while( cin >> key )48 {49 //cin >> key;50 if( key == -99 )51 {52 //break;53 return;54 }55 if( SL1.binarySearch(key) != -1 )56 {57 cout << key << " is in the sequence list." << endl;58 }59 else60 {61 cout << key << " is not in the sequence list." << endl;62 }63 }64 65 }66 67 int main(int argc, char* argv[])68 {69 test2();70 71 return 0;72 }
二分查找(排序)树:
1 // stdafx.h : include file for standard system include files, 2 // or project specific include files that are used frequently, but 3 // are changed infrequently 4 // 5 6 #if !defined(AFX_STDAFX_H__239FA301_F6C5_4AE4_BD82_5EB3365C7ECB__INCLUDED_) 7 #define AFX_STDAFX_H__239FA301_F6C5_4AE4_BD82_5EB3365C7ECB__INCLUDED_ 8 9 #if _MSC_VER > 100010 #pragma once11 #endif // _MSC_VER > 100012 13 14 #include15 #include 16 17 using namespace std;18 19 //将 elementType 设为 int 可以顺利完成实验要求;而将其设为 string 则可以输入字符串等,20 //此时的大小关系默认为为字典序21 //typedef string elementType;22 typedef int elementType;23 24 //为了图好玩,调用EasyX库把字体颜色改了一下25 //这是EasyX的官方网站: https://www.easyx.cn/26 27 typedef struct node28 {29 elementType data;30 struct node *leftChidld, *rightChild; 31 }BSTNode, *_BSTree;32 33 // TODO: reference additional headers your program requires here34 35 //{ {AFX_INSERT_LOCATION}}36 // Microsoft Visual C++ will insert additional declarations immediately before the previous line.37 38 #endif // !defined(AFX_STDAFX_H__239FA301_F6C5_4AE4_BD82_5EB3365C7ECB__INCLUDED_)
1 // BSTree.h: interface for the BSTree class. 2 // 3 // 4 5 #if !defined(AFX_BSTREE_H__37E371A7_E165_4AC3_898B_DDF38B0F87D8__INCLUDED_) 6 #define AFX_BSTREE_H__37E371A7_E165_4AC3_898B_DDF38B0F87D8__INCLUDED_ 7 8 #if _MSC_VER > 1000 9 #pragma once10 #endif // _MSC_VER > 100011 12 class BSTree 13 {14 public:15 BSTree();16 virtual ~BSTree();17 BSTNode *search( _BSTree BST, elementType value );//递归查找18 BSTNode *search( _BSTree BST, elementType value, _BSTree &father );//迭代查找19 BSTNode *getRootNode();20 bool insert( _BSTree BST, elementType value );21 22 bool deleteNode1( _BSTree &BST, elementType value ); //删除指定结点,failed23 void deleteNode2( _BSTree &BST, elementType value ); //递归删除指定结点24 void deleteNode2_1( _BSTree &BST, elementType value ); //迭代删除指定结点,待调试!25 void deleteNode3( _BSTree &BST, elementType value );26 27 void removeNode1( _BSTree &BST );28 void removeNode2( _BSTree &BST );29 void removeNode3( _BSTree &BST );30 31 void createBinarySearchTree( _BSTree BST, vectorVI/*elementType value*/ );32 void destroy( _BSTree BST );33 void preOrderTraversal( _BSTree BST/*, int space*/ );34 void inOrderTraversal( _BSTree BST/*, int space*/ );35 void postOrderTraversal( _BSTree BST/*, int space*/ );36 private:37 BSTNode *head;38 };39 40 #endif // !defined(AFX_BSTREE_H__37E371A7_E165_4AC3_898B_DDF38B0F87D8__INCLUDED_)
1 // BSTree.cpp: implementation of the BSTree class. 2 // 3 // 4 5 #include "stdafx.h" 6 #include "BSTree.h" 7 8 // 9 // Construction/Destruction 10 // 11 12 BSTree::BSTree() 13 { 14 //head = NULL; 15 //head = new BSTNode; 16 //head->leftChidld = head->rightChild = NULL; 17 } 18 19 BSTree::~BSTree() 20 { 21 ios::sync_with_stdio(false); 22 destroy(head); 23 cout << "The binary search tree has been destroyed!" << endl; 24 } 25 26 void BSTree::destroy( _BSTree BST ) 27 { 28 if(BST) 29 { 30 destroy( BST->leftChidld ); 31 destroy( BST->rightChild ); 32 delete BST; 33 } 34 } 35 36 void BSTree::preOrderTraversal( _BSTree BST/*, int space*/ ) 37 { 38 ios::sync_with_stdio(false); 39 /* 40 if(!BST) 41 { 42 cerr << "The binary search tree is empty.Error in void BSTree::preOrderTraversal( _BSTree BST )." << endl; 43 return; 44 } 45 */ 46 if(BST) 47 { 48 cout << BST->data << " "; 49 preOrderTraversal( BST->leftChidld ); 50 preOrderTraversal( BST->rightChild ); 51 52 //for( int i = 0; i < space; i ++ ) 53 // cout << " "; 54 //cout << BST->data << endl; 55 //preOrderTraversal( BST->leftChidld, space + 5 ); 56 //preOrderTraversal( BST->rightChild, space + 5 ); 57 } 58 } 59 60 void BSTree::inOrderTraversal( _BSTree BST/*, int space*/ ) 61 { 62 ios::sync_with_stdio(false); 63 if(BST) 64 { 65 inOrderTraversal( BST->leftChidld ); 66 cout << BST->data << " "; 67 inOrderTraversal( BST->rightChild ); 68 69 //inOrderTraversal( BST->leftChidld, space + 5 ); 70 //for( int i = 0; i < space; i ++ ) 71 // cout << " "; 72 //cout << BST->data << endl; 73 //inOrderTraversal( BST->rightChild, space + 5 ); 74 } 75 } 76 77 void BSTree::postOrderTraversal( _BSTree BST/*, int space*/ ) 78 { 79 ios::sync_with_stdio(false); 80 if(BST) 81 { 82 postOrderTraversal( BST->leftChidld ); 83 postOrderTraversal( BST->rightChild ); 84 cout << BST->data << " "; 85 86 /* 87 postOrderTraversal( BST->leftChidld, space + 5 ); 88 postOrderTraversal( BST->rightChild, space + 5 ); 89 for( int i = 0; i < space; i ++ ) 90 cout << " "; 91 cout << BST->data << endl; 92 */ 93 } 94 } 95 96 void BSTree::createBinarySearchTree( _BSTree BST, /*elementType value*/vectorVI ) 97 { 98 //BST = NULL; 99 head = NULL;100 for( int i = 0; i < VI.size(); i ++ )101 {102 insert( head, VI[i] );103 }104 return;105 /*106 while( cin >> value )107 {108 if( value == "#" )109 {110 return;111 }112 else113 insert( head, value );114 }115 116 for( int i = 0; i < value; i ++ )117 {118 elementType key;119 cout << "input: ";120 cin >> key;121 insert( head, key );122 }123 */124 }125 126 BSTNode *BSTree::getRootNode()127 {128 return head;129 }130 131 BSTNode *BSTree::search( _BSTree BST, elementType value )//递归查找132 {133 ios::sync_with_stdio(false);134 if(!head)135 {136 cerr << "The binary search tree is empty.Error in BSTNode *BSTree::search( _BSTree BST, elementType value )." << endl;137 return NULL;138 }139 else if( BST->data == value )140 {141 return BST;142 }143 else if( BST->data > value )144 {145 return search( BST->leftChidld, value );146 }147 else148 {149 return search( BST->rightChild, value );150 }151 }152 153 BSTNode *BSTree::search( _BSTree BST, elementType value, _BSTree &father )//迭代查找154 {155 ios::sync_with_stdio(false);156 /*157 if(!head)158 {159 cerr << "The binary search tree empty.Error in BSTNode *BSTree::search( _BSTree BST, elementType value, _BSTree &father )." << endl;160 return NULL;161 }162 */163 BSTNode *tmp = head;164 father = NULL;165 while( tmp && tmp->data != value )166 {167 father = tmp;168 if( value < tmp->data )169 {170 tmp = tmp->leftChidld;171 }172 else173 {174 tmp = tmp->rightChild;175 }176 }177 return tmp;178 }179 180 bool BSTree::insert( _BSTree BST, elementType value )181 {182 //if(!head)183 //{184 // cerr << "The binary search tree does not exit.Error in bool BSTree::insert( _BSTree BST, elementType value )" << endl;185 // return false;186 //}187 BSTNode *newNode, *target, *father;188 189 target = search( head, value, father );190 if(target)191 {192 cerr << "Inserting failed!" << value << " has been exited in the binary search tree.\nError in bool BSTree::insert( _BSTree BST, elementType value )" << endl;193 return false;194 }195 newNode = new BSTNode;196 newNode->data = value;197 newNode->leftChidld = newNode->rightChild = NULL;198 if(!head)199 {200 head = newNode;201 }202 else if( value < father->data )203 {204 father->leftChidld = newNode;205 }206 else207 {208 father->rightChild = newNode;209 }210 return true;211 }212 213 bool BSTree::deleteNode1( _BSTree &BST, elementType value )214 {215 ios::sync_with_stdio(false);216 //if(!head)217 if(!BST)218 {219 cerr << "The binary search tree does not exit.Error in bool BSTree::deleteNode( _BSTree BST, elementType value )" << endl;220 return false;221 }222 BSTNode *newNode, *target, *father;223 //target = search( head, value, father );224 target = search( BST, value, father );225 if( !target )//查找失败,不删除226 {227 cerr << "Node-deleting failed!\n" << value << " is not in the binary search tree.\n" << "Error in bool BSTree::deleteNode( _BSTree BST, elementType value )." << endl;228 return false;229 }230 if( target->leftChidld && target->rightChild )//被删结点有两个 *target 孩子节点231 {232 newNode = target->rightChild; //找 target 的中序后继 newNode233 father = target;234 while( newNode->leftChidld )235 {236 father = newNode;237 newNode = newNode->leftChidld;238 }239 target->data = newNode->data; //将 *newNode 的数据传給 *target240 target = newNode; //找到的这个结点成为被删除结点241 }242 if( target->leftChidld ) //单孩子,记录非空孩子结点243 {244 newNode = target->leftChidld;245 }246 else247 {248 newNode = target->rightChild;249 }250 //if( target == head ) //被删结点是根结点251 if( target == BST )252 {253 //head = newNode;254 BST = newNode;255 }256 else if( newNode && ( newNode->data < father->data ) ) //重新链接,保持二叉排序树257 {258 father->leftChidld = newNode;259 }260 else261 {262 father->rightChild = newNode;263 }264 delete target;265 return true;266 }267 268 void BSTree::deleteNode2( _BSTree &BST, elementType value )269 {270 if(BST)271 {272 if( value < BST->data )273 {274 deleteNode2( BST->leftChidld, value );275 }276 else if( value > BST->data )277 {278 deleteNode2( BST->rightChild, value );279 }280 else281 {282 removeNode1(BST);283 }284 }285 }286 287 void BSTree::deleteNode2_1( _BSTree &BST, elementType value ) //迭代删除指定结点,待调试!288 {289 BSTNode *target = NULL;290 while( BST || BST->data != value )291 {292 target = BST;293 if( value < target->data )294 //if( value < BST->data )295 BST = BST->leftChidld;296 else297 BST = BST->rightChild;298 }299 removeNode1(target);300 //removeNode1(BST);301 }302 303 void BSTree::deleteNode3( _BSTree &BST, elementType value )304 {305 if(BST)306 {307 if( value < BST->data )308 {309 deleteNode2( BST->leftChidld, value );310 }311 else if( value > BST->data )312 {313 deleteNode2( BST->rightChild, value );314 }315 else316 {317 removeNode2(BST);318 }319 }320 }321 /*322 在二叉查找树中删除一个给定的结点p有三种情况323 324 (1)结点p无左右子树,则直接删除该结点,修改父节点相应指针325 326 (2)结点p有左子树(右子树),则把p的左子树(右子树)接到p的父节点上327 328 (3)左右子树同时存在,则有三种处理方式329 330 a.找到结点p的中序直接前驱结点s,把结点s的数据转移到结点p,然后删除结点s,331 由于结点s为p的左子树中最右的结点,因而s无右子树,删除结点s可以归结到情况(2)。332 严蔚敏数据结构P230-231就是该处理方式。333 b.找到结点p的中序直接后继结点s,把结点s的数据转移到结点p,然后删除结点s,334 由于结点s为p的右子树总最左的结点,因而s无左子树,删除结点s可以归结到情况(2)。335 算法导论第2版P156-157该是该处理方式。336 c.到p的中序直接前驱s,将p的左子树接到父节点上,将p的右子树接到s的右子树上,然后删除结点p。337 */338 void BSTree::removeNode1( _BSTree &BST )339 {340 BSTNode *target = NULL;341 if( !BST->leftChidld )342 {343 target = BST;344 BST = BST->rightChild;345 delete target;346 }347 else if( !BST->rightChild )348 {349 target = BST;350 BST = BST->leftChidld;351 delete target;352 }353 else354 {355 BSTNode *newNode = NULL;356 target = BST;357 newNode = BST->leftChidld; //左子树根结点 358 while( newNode->rightChild ) //寻找 BST 结点的中序前驱结点,即以 BST->leftChild为根结点的子树中的最右结点359 {360 target = newNode; //*target 指向 *BST 的父结点 361 newNode = newNode->rightChild; //*newNode 指向 *BST 的中序前驱结点362 }363 BST->data = newNode->data; //*newNode 的数据传給 *BST 的数据,然后删除结点 *newNode364 if( target != BST ) //BST->leftChidld 的右子树非空,这句话等价于 if( !( target == BST ) )365 {366 target->rightChild = newNode->leftChidld; //*newNode 的左子树接到 *target 的右子树上 367 }368 else369 {370 target->leftChidld = newNode->leftChidld; //*newNode 的左子树接到 *target 的左子树上371 }372 delete newNode; //删除结点 *newNode373 }374 }375 376 //注意 while 循环体:377 //如果 BST 左子树为空,则 while 循环体不执行,那么 target 就不会发生改变。 378 //然而一开始 target == BST。379 //反过来说,如果 BST 左子树不为空,则 while 执行,那么 target 就会发生改变。380 //target 改变了,就和 BST 不一样。381 //所以就可以表明 BST 左子树非空。382 383 void BSTree::removeNode2( _BSTree &BST )384 {385 BSTNode *target = NULL;386 if( !BST->leftChidld )387 {388 target = BST;389 BST = BST->rightChild;390 delete target;391 }392 else if( !BST->rightChild )393 {394 target = BST;395 BST = BST->leftChidld;396 delete target;397 }398 else399 {400 BSTNode *newNode = NULL;401 target = BST;402 newNode = BST->rightChild; //右子树根结点403 while( newNode->leftChidld ) //寻找 BST 结点的中序前驱结点,即以 BST->leftChild为根结点的子树中的最左结点404 {405 target = newNode; //*target 指向 *BST 的父结点406 newNode = newNode->leftChidld; //*newNode 指向 *BST 的中序后继结点407 }408 BST->data = newNode->data; //*newNode 的数据传給 *BST 的数据,然后删除结点 *newNode409 if( target != BST ) //BST->leftChidld 的左子树非空,这句话等价于 if( !( target == BST ) )410 {411 target->leftChidld = newNode->rightChild; //*newNode 的右子树接到 *target 的左子树上 412 }413 else414 {415 target->rightChild = newNode->rightChild; //*newNode 的右子树接到 *target 的右子树上 416 }417 delete newNode; //删除结点 *newNode418 }419 }420 421 //注意 while 循环体:422 //如果 BST 右子树为空,则 while 循环体不执行,那么 target 就不会发生改变。 423 //然而一开始 target == BST。424 //反过来说,如果 BST 右子树不为空,则 while 执行,那么 target 就会发生改变。425 //target 改变了,就和 BST 不一样426 //所以就可以表明 BST 右子树非空。427 428 429 void BSTree::removeNode3( _BSTree &BST ) 430 {431 BSTNode *target = NULL;432 if( !BST->leftChidld )433 {434 target = BST;435 BST = BST->rightChild;436 delete target;437 }438 else if( !BST->rightChild )439 {440 target = BST;441 BST = BST->leftChidld;442 delete target;443 }444 else445 {446 BSTNode *newNode = NULL;447 target = BST;448 newNode = BST->leftChidld; //左子树根结点449 while( newNode->rightChild ) //寻找 BST 结点的中序前驱结点,即以 BST->leftChild为根结点的子树中的最右结点450 {451 //target = newNode;452 newNode = newNode->rightChild;453 }454 newNode->rightChild = target->leftChidld; //*target 的左子树接到 *newNode 的左子树上455 target = target->leftChidld; //*target 的左子树接到父结点上456 delete target; //删除结点 *target457 }458 }
1 // BinarySearchTree.cpp : Defines the entry point for the console application. 2 // 3 4 #include "stdafx.h" 5 #include "BSTree.h" 6 7 //这是EasyX的官方网站: https://www.easyx.cn/ 8 9 void test1() 10 { 11 HANDLE hOut; 12 13 // 获取输出流的句柄 14 hOut = GetStdHandle(STD_OUTPUT_HANDLE); 15 16 BSTree BST1; 17 elementType value; 18 vectorVI; 19 while( cin >> value ) 20 { 21 if( (char)value == '#' && value != 35/*-999*/ ) //细节处理:一定要加 && value != 35,因为 # 的ASCII码是35, 22 { //不加的话在输入数字“35”而不是“#”时循环也会终止 23 break; 24 } 25 else 26 { 27 VI.push_back(value); 28 } 29 30 } 31 BST1.createBinarySearchTree( BST1.getRootNode(), VI ); 32 33 SetConsoleTextAttribute(hOut, 34 FOREGROUND_RED | // 前景色_红色 35 FOREGROUND_BLUE |// 前景色_蓝色 36 FOREGROUND_INTENSITY);// 加强 37 38 cout << "PreOrder:" << endl; 39 BST1.preOrderTraversal( BST1.getRootNode() ); 40 cout << endl; 41 cout << "InOrder:" << endl; 42 BST1.inOrderTraversal( BST1.getRootNode() ); 43 cout << endl; 44 cout << "PostOrder:" << endl; 45 BST1.postOrderTraversal( BST1.getRootNode() ); 46 cout << endl; 47 48 SetConsoleTextAttribute(hOut, 49 FOREGROUND_RED | // 前景色_红色 50 FOREGROUND_GREEN | // 前景色_绿色 51 FOREGROUND_BLUE ); // 前景色_蓝色 52 53 return; 54 } 55 56 void test2() 57 { 58 HANDLE hOut; 59 60 // 获取输出流的句柄 61 hOut = GetStdHandle(STD_OUTPUT_HANDLE); 62 63 BSTree BST1; 64 elementType value; 65 vector VI; 66 67 while( cin >> value ) 68 { 69 if( (char)value == '#' && value != 35/*-999*/ ) //细节处理:一定要加 && value != 35,因为 # 的ASCII码是35, 70 { //不加的话在输入数字“35”而不是“#”时循环也会终止 71 break; 72 } 73 else 74 { 75 VI.push_back(value); 76 } 77 78 } 79 80 BST1.createBinarySearchTree( BST1.getRootNode(), VI ); 81 82 _BSTree index = NULL; 83 84 SetConsoleTextAttribute(hOut, 85 FOREGROUND_RED | // 前景色_红色 86 FOREGROUND_BLUE |// 前景色_蓝色 87 FOREGROUND_INTENSITY);// 加强 88 89 cout << "PreOrder:" << endl; 90 91 BST1.preOrderTraversal( BST1.getRootNode() ); 92 cout << endl; 93 cout << "InOrder:" << endl; 94 BST1.inOrderTraversal( BST1.getRootNode() ); 95 cout << endl; 96 cout << "PostOrder:" << endl; 97 BST1.postOrderTraversal( BST1.getRootNode() ); 98 cout << endl; 99 100 101 102 //elementType key = ;// = 545;103 //下面这句话不会运行104 //cin >> key;105 106 elementType Arr[] = { 150, 70, 160, 190, 10, 55, 175 };107 108 for( int j = 0; j < sizeof(Arr) / sizeof(elementType); j ++ )109 {110 if( BST1.search( BST1.getRootNode(), Arr[j], index ) )111 {112 SetConsoleTextAttribute(hOut, 113 FOREGROUND_BLUE | // 前景色_蓝色114 FOREGROUND_INTENSITY ); // 前景色_加强115 cout << Arr[j] << " is in the binary search tree." << endl;116 SetConsoleTextAttribute(hOut, 117 FOREGROUND_RED | // 前景色_红色118 FOREGROUND_GREEN | // 前景色_绿色119 FOREGROUND_BLUE ); // 前景色_蓝色120 }121 else122 {123 SetConsoleTextAttribute(hOut, 124 FOREGROUND_RED | // 前景色_红色125 FOREGROUND_INTENSITY ); // 前景色_加强126 cout << Arr[j] << " is not in the binary search tree." << endl;127 SetConsoleTextAttribute(hOut, 128 FOREGROUND_RED | // 前景色_红色129 FOREGROUND_GREEN | // 前景色_绿色130 FOREGROUND_BLUE ); // 前景色_蓝色131 }132 }133 134 //无法实现下面这样输入数值判断其是否存在135 /*136 BSTNode *father = NULL, *target = NULL;137 138 elementType key;139 while( cin >> key )140 {141 //target = NULL;142 if( (char)key == '#' && key != 35 ) 143 { 144 break;145 }146 else147 target = BST1.search( BST1.getRootNode(), key, father );148 149 if(!target)150 {151 cout << "No!" << endl;152 }153 else154 {155 cout << "Yes!" << endl;156 }157 158 }159 */ 160 161 return;162 }163 164 void test3()165 {166 HANDLE hOut; 167 168 // 获取输出流的句柄169 hOut = GetStdHandle(STD_OUTPUT_HANDLE); 170 171 BSTree BST1;172 elementType value;173 vector VI;174 175 while( cin >> value )176 {177 if( (char)value == '#' && value != 35/*-999*/ ) //细节处理:一定要加 && value != 35,因为 # 的ASCII码是35,178 { //不加的话在输入数字“35”而不是“#”时循环也会终止179 break;180 }181 else182 {183 VI.push_back(value);184 }185 186 }187 188 BST1.createBinarySearchTree( BST1.getRootNode(), VI );189 190 _BSTree index = NULL; 191 192 SetConsoleTextAttribute(hOut, 193 FOREGROUND_BLUE | // 前景色_蓝色194 FOREGROUND_INTENSITY ); // 前景色_加强195 cout << "The origin binary search tree is as follow:" << endl;196 SetConsoleTextAttribute(hOut, 197 FOREGROUND_RED | // 前景色_红色198 FOREGROUND_BLUE |// 前景色_蓝色199 FOREGROUND_INTENSITY);// 加强200 201 cout << "PreOrder:" << endl;202 203 BST1.preOrderTraversal( BST1.getRootNode() );204 cout << endl;205 cout << "InOrder:" << endl;206 BST1.inOrderTraversal( BST1.getRootNode() );207 cout << endl;208 cout << "PostOrder:" << endl;209 BST1.postOrderTraversal( BST1.getRootNode() );210 211 cout << endl;212 213 214 215 elementType Arr[] = { 30, 150, 100 };216 for( int i = 0; i < sizeof(Arr) / sizeof(elementType); i ++ )217 { 218 _BSTree index = BST1.getRootNode();219 //BST1.deleteNode1( index, Arr[i] );220 BST1.deleteNode2( index, Arr[i] );221 SetConsoleTextAttribute(hOut, 222 FOREGROUND_BLUE | // 前景色_蓝色223 FOREGROUND_INTENSITY ); // 前景色_加强224 cout << "After deleting node " << Arr[i] << ", the current binary search tree is as follow:"<< endl;225 226 SetConsoleTextAttribute(hOut, 227 FOREGROUND_RED | // 前景色_红色228 FOREGROUND_BLUE |// 前景色_蓝色229 FOREGROUND_INTENSITY);// 加强230 231 cout << "PreOrder:" << endl;232 233 BST1.preOrderTraversal( BST1.getRootNode() );234 cout << endl;235 cout << "InOrder:" << endl;236 BST1.inOrderTraversal( BST1.getRootNode() );237 cout << endl;238 cout << "PostOrder:" << endl;239 BST1.postOrderTraversal( BST1.getRootNode() );240 cout << endl;241 242 }243 SetConsoleTextAttribute(hOut, 244 FOREGROUND_RED | // 前景色_红色245 FOREGROUND_GREEN | // 前景色_绿色246 FOREGROUND_BLUE ); // 前景色_蓝色247 return;248 }249 250 251 int main(int argc, char* argv[])252 {253 //test1();254 //test2();255 test3();256 return 0;257 }
AVL树:
1 // Tips for Getting Started: 2 // 1. Use the Solution Explorer window to add/manage files 3 // 2. Use the Team Explorer window to connect to source control 4 // 3. Use the Output window to see build output and other messages 5 // 4. Use the Error List window to view errors 6 // 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project 7 // 6. In the future, to open this project again, go to File > Open > Project and select the .sln file 8 9 #ifndef PCH_H10 #define PCH_H11 12 #include13 #include 14 #include 15 #include 16 17 using namespace std;18 19 // TODO: add headers that you want to pre-compile here20 21 #endif //PCH_H
1 #pragma once 2 /* AVL node */ 3 template4 class AVLNode 5 { 6 public: 7 T key; 8 int balance; 9 AVLNode *leftChild, *rightChild, *parent;10 11 AVLNode(T k, AVLNode *p) : key(k), balance(0), parent(p),leftChild(NULL), rightChild(NULL) {}12 ~AVLNode();13 };
1 #pragma once 2 /* AVL tree */ 3 4 #include "AVLnode.h" 5 template6 class AVLTree 7 { 8 public: 9 AVLTree(void);10 ~AVLTree(void);11 bool insert(T key);12 void deleteKey(const T key);13 void printBalance();14 void inOrderTraverse();15 void preOrderTraverse();16 void postOrderTraverse();17 void display();18 19 AVLNode * RR_Rotate(AVLNode *AVLB); //rotate left20 //当在RR发生不平衡时需要进行左旋转21 AVLNode * LL_Rotate(AVLNode *AVLB); //rotate right22 //当在LL发生不平衡时需要进行右旋转23 AVLNode * LR_Rotate(AVLNode *AVLB); //rotate left then right24 AVLNode * RL_Rotate(AVLNode *AVLB); //rotate right then left25 AVLNode * getRootNode();26 void reBalance(AVLNode *AVLB);27 int height(AVLNode *AVLB);28 void setBalance(AVLNode *AVLB);29 void printBalance(AVLNode *AVLB);30 void clearNode(AVLNode *AVLB);31 void inOrderTraverse(AVLNode *AVLB);32 void preOrderTraverse(AVLNode *AVLB);33 void postOrderTraverse(AVLNode *AVLB);34 35 void display(AVLNode *AVLB, int space, int colour);36 37 private:38 AVLNode *root;39 };
1 #include "pch.h" 2 #include "AVLnode.h" 3 4 5 template6 AVLNode ::~AVLNode() 7 { 8 delete leftChild; 9 delete rightChild;10 }
1 #include "pch.h" 2 #include "AVLtree.h" 3 4 5 template6 void AVLTree ::reBalance(AVLNode *AVLB) 7 { 8 setBalance(AVLB); 9 10 if (AVLB->balance == -2) 11 { 12 if (height(AVLB->leftChild->leftChild) >= height(AVLB->leftChild->rightChild)) 13 AVLB = LL_Rotate(AVLB); 14 else 15 AVLB = LR_Rotate(AVLB); 16 } 17 else if (AVLB->balance == 2) 18 { 19 if (height(AVLB->rightChild->rightChild) >= height(AVLB->rightChild->leftChild)) 20 AVLB = RR_Rotate(AVLB); 21 else 22 AVLB = RL_Rotate(AVLB); 23 } 24 25 if (AVLB->parent != NULL) 26 { 27 reBalance(AVLB->parent); 28 } 29 else 30 { 31 root = AVLB; 32 } 33 } 34 35 template 36 AVLNode * AVLTree ::RR_Rotate(AVLNode *AVLB) 37 { 38 AVLNode *tmp = AVLB->rightChild; 39 tmp->parent = AVLB->parent; 40 AVLB->rightChild = tmp->leftChild; 41 42 if (AVLB->rightChild != NULL) 43 AVLB->rightChild->parent = AVLB; 44 45 tmp->leftChild = AVLB; 46 AVLB->parent = tmp; 47 48 if (tmp->parent != NULL) 49 { 50 if (tmp->parent->rightChild == AVLB) 51 { 52 tmp->parent->rightChild = tmp; 53 } 54 else 55 { 56 tmp->parent->leftChild = tmp; 57 } 58 } 59 60 setBalance(AVLB); 61 setBalance(tmp); 62 return tmp; 63 } 64 65 template 66 AVLNode * AVLTree ::LL_Rotate(AVLNode *AVLB) 67 { 68 AVLNode *tmp = AVLB->leftChild; 69 tmp->parent = AVLB->parent; 70 AVLB->leftChild = tmp->rightChild; 71 72 if (AVLB->leftChild != NULL) 73 AVLB->leftChild->parent = AVLB; 74 75 tmp->rightChild = AVLB; 76 AVLB->parent = tmp; 77 78 if (tmp->parent != NULL) 79 { 80 if (tmp->parent->rightChild == AVLB) 81 { 82 tmp->parent->rightChild = tmp; 83 } 84 else 85 { 86 tmp->parent->leftChild = tmp; 87 } 88 } 89 90 setBalance(AVLB); 91 setBalance(tmp); 92 return tmp; 93 } 94 95 template 96 AVLNode * AVLTree ::LR_Rotate(AVLNode *AVLB) 97 { 98 AVLB->leftChild = RR_Rotate(AVLB->leftChild); 99 return LL_Rotate(AVLB);100 }101 102 template 103 AVLNode * AVLTree ::RL_Rotate(AVLNode *AVLB)104 {105 AVLB->rightChild = LL_Rotate(AVLB->rightChild);106 return RR_Rotate(AVLB);107 }108 109 template 110 AVLNode * AVLTree ::getRootNode()111 {112 return root;113 }114 115 template 116 int AVLTree ::height(AVLNode *AVLB)117 {118 if (AVLB == NULL)119 return -1;120 return 1 + max(height(AVLB->leftChild), height(AVLB->rightChild));121 }122 123 template 124 void AVLTree ::setBalance(AVLNode *AVLB)125 {126 AVLB->balance = height(AVLB->rightChild) - height(AVLB->leftChild);127 }128 129 template 130 void AVLTree ::printBalance(AVLNode *AVLB)131 {132 ios::sync_with_stdio(false);133 if (AVLB != NULL)134 {135 printBalance(AVLB->leftChild);136 cout << AVLB->balance << " ";137 //std::cout << n->key << " ";138 printBalance(AVLB->rightChild);139 }140 }141 142 template 143 void AVLTree ::inOrderTraverse(AVLNode *AVLB)144 {145 ios::sync_with_stdio(false);146 if (AVLB)147 {148 inOrderTraverse(AVLB->leftChild);149 cout << AVLB->key << " ";150 inOrderTraverse(AVLB->rightChild);151 }152 }153 154 template 155 void AVLTree ::preOrderTraverse(AVLNode *AVLB)156 {157 if (AVLB)158 {159 cout << AVLB->key << " ";160 preOrderTraverse(AVLB->leftChild);161 preOrderTraverse(AVLB->rightChild);162 }163 }164 165 template 166 void AVLTree ::postOrderTraverse(AVLNode *AVLB)167 {168 ios::sync_with_stdio(false);169 if (AVLB)170 {171 postOrderTraverse(AVLB->leftChild);172 postOrderTraverse(AVLB->rightChild);173 cout << AVLB->key << " ";174 }175 }176 177 template 178 void AVLTree ::display(AVLNode *AVLB, int space, int colour )179 {180 ios::sync_with_stdio(false);181 HANDLE hConsole;182 hConsole = GetStdHandle(STD_OUTPUT_HANDLE);183 if (AVLB)184 {185 display(AVLB->rightChild, space + 1, colour + 1);186 SetConsoleTextAttribute(hConsole, 0x0008 | colour);187 //colour++;188 cout << endl;189 if (AVLB == root)190 cout << " Root ----> ";191 for (int i = 0; i < space && AVLB != root; i++)192 cout << " ";193 cout << AVLB->key;194 display(AVLB->leftChild, space + 1, colour + 1);195 }196 }197 198 template 199 AVLTree ::AVLTree(void) : root(NULL) {}200 201 template 202 AVLTree ::~AVLTree(void)203 {204 delete root;205 }206 207 template 208 bool AVLTree ::insert(T key)209 {210 if (root == NULL)211 {212 root = new AVLNode (key, NULL);213 }214 else215 {216 AVLNode //这种风格我觉得不错217 //I appreciate this style of code218 *target = root, 219 *parent;220 221 while (1)222 {223 if (target->key == key)224 return false;225 226 parent = target;227 228 bool goLeft = target->key > key;229 target = goLeft ? target->leftChild : target->rightChild;230 231 if (target == NULL)232 {233 if (goLeft)234 {235 parent->leftChild = new AVLNode (key, parent);236 }237 else238 {239 parent->rightChild = new AVLNode (key, parent);240 }241 242 reBalance(parent);243 break;244 }245 }246 }247 248 return true;249 }250 251 template 252 void AVLTree ::deleteKey(const T delKey)253 {254 if (root == NULL)255 return;256 257 AVLNode 258 *target = root,259 *parent = root,260 *delNode = NULL,261 *child = root;262 263 while (child != NULL)264 {265 parent = target;266 target = child;267 child = delKey >= target->key ? target->rightChild : target->leftChild;268 if (delKey == target->key)269 delNode = target;270 }271 272 if (delNode != NULL)273 {274 delNode->key = target->key;275 276 child = target->leftChild != NULL ? target->leftChild : target->rightChild;277 278 if (root->key == delKey)279 {280 root = child;281 }282 else283 {284 if (parent->leftChild == target)285 {286 parent->leftChild = child;287 }288 else289 {290 parent->rightChild = child;291 }292 293 reBalance(parent);294 }295 }296 }297 298 template 299 void AVLTree ::printBalance()300 {301 ios::sync_with_stdio(false);302 printBalance(root);303 cout << endl;304 }305 306 template 307 void AVLTree ::inOrderTraverse()308 {309 ios::sync_with_stdio(false);310 inOrderTraverse(root);311 cout << endl;312 }313 314 template 315 void AVLTree ::preOrderTraverse()316 {317 ios::sync_with_stdio(false);318 preOrderTraverse(root);319 cout << endl;320 }321 322 template 323 void AVLTree ::postOrderTraverse()324 {325 ios::sync_with_stdio(false);326 postOrderTraverse(root);327 cout << endl;328 }329 330 template 331 void AVLTree ::display()332 {333 ios::sync_with_stdio(false);334 int color = 1;335 display(root, 1, color);336 cout << endl;337 }
1 // AVL_2.cpp : This file contains the 'main' function. Program execution begins and ends there. 2 // 3 4 #include "pch.h" 5 #include6 #include "AVLtree.h" 7 #include "AVLnode.h" 8 #include "AVLnode.cpp" 9 #include "AVLtree.cpp" 10 11 int main() 12 { 13 //std::cout << "Hello World!\n"; 14 ios::sync_with_stdio(false); 15 AVLTree AVLBT; 16 HANDLE hConsole; 17 hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 18 cout << "Inserting integer values 1 to 26" << std::endl; 19 int Arr[] = { 1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210,231, 20 253,277,302,328 }; 21 for (int i = 0; i < sizeof(Arr) / sizeof(int); i++) 22 //for( int i = 0; Arr[i] != 0; i ++ ) 23 //AVLBT.insert(i); 24 AVLBT.insert(Arr[i]); 25 26 cout << "Printing the balance factor of each node: " << std::endl; 27 SetConsoleTextAttribute(hConsole, 12); 28 AVLBT.printBalance(); 29 SetConsoleTextAttribute(hConsole, 7); 30 cout << "Printing key: " << std::endl; 31 SetConsoleTextAttribute(hConsole, 0x0008 | 8); 32 AVLBT.inOrderTraverse(); 33 AVLBT.display(); 34 //AVLTree *root = avl.getRootNode(); 35 while (1) 36 { 37 SetConsoleTextAttribute(hConsole, 7); 38 cout << "\n---------------------" << endl; 39 cout << "AVL tree implementation" << endl; 40 cout << "By Utah Xef developed" << endl; 41 cout << "\n---------------------" << endl; 42 cout << "1.insert element into the tree" << endl; 43 cout << "2.display balanced AVL tree" << endl; 44 cout << "3.preorder traversal" << endl; 45 cout << "4.inorder traversal" << endl; 46 cout << "5.postorder traversal" << endl; 47 cout << "6.delete key" << endl; 48 cout << "7.display the balance factor of each node" << endl; 49 cout << "8.exit" << endl; 50 cout << "enter your choice: "; 51 int choice; 52 cin >> choice; 53 54 switch (choice) 55 56 { 57 58 case 1: 59 60 cout << "enter value to be inserted: "; 61 int item; 62 cin >> item; 63 64 AVLBT.insert(item); 65 66 break; 67 68 case 2: 69 70 if (AVLBT.getRootNode() == nullptr) 71 72 { 73 74 cout << "tree is empty" << endl; 75 76 continue; 77 78 } 79 80 cout << "balanced avl tree:" << endl; 81 82 AVLBT.display(); 83 84 break; 85 86 case 3: 87 88 cout << "preorder traversal:" << endl; 89 SetConsoleTextAttribute(hConsole, 0x0008 | 9); 90 AVLBT.preOrderTraverse(); 91 92 cout << endl; 93 94 break; 95 case 4: 96 97 cout << "inorder traversal:" << endl; 98 SetConsoleTextAttribute(hConsole, 0x0008 | 10); 99 AVLBT.inOrderTraverse();100 101 cout << endl;102 103 break;104 105 106 107 case 5:108 109 cout << "postorder traversal:" << endl;110 SetConsoleTextAttribute(hConsole, 0x0008 | 11);111 AVLBT.postOrderTraverse();112 113 cout << endl;114 115 break;116 117 case 6:118 int value;119 cout << "Please input the value to delete:" << endl;120 cin >> value;121 AVLBT.deleteKey(value);122 break;123 124 case 7:125 cout << "The balance factor of each node:" << endl;126 SetConsoleTextAttribute(hConsole, 0x0008 | 14);127 AVLBT.printBalance();128 break;129 case 8:130 exit(1);131 132 break;133 default:134 135 cout << "Wrong choice" << endl;136 break;137 }138 139 }140 //std::cout << std::endl;141 std::cin.get();142 }143 144 // Run program: Ctrl + F5 or Debug > Start Without Debugging menu145 // Debug program: F5 or Debug > Start Debugging menu146 147 // Tips for Getting Started: 148 // 1. Use the Solution Explorer window to add/manage files149 // 2. Use the Team Explorer window to connect to source control150 // 3. Use the Output window to see build output and other messages151 // 4. Use the Error List window to view errors152 // 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project153 // 6. In the future, to open this project again, go to File > Open > Project and select the .sln file