一步一步写数据结构(BST-二叉排序树)
二叉排序树的重要性不用多说,下面用c++实现二叉排序树的建立,插入,查找,修改,和删除。难点在于删除,其他几个相对比较简单。
以下是代码:
1 #include<iostream> 2 using namespace std; 3 //定义节点 4 typedef struct BiNode 5 { 6 int data; 7 struct BiNode *lchild,*rchild; 8 }BiNode,*BiTree; 9 10 //插入函数 11 void insertBST(BiTree &T,int key) 12 { 13 if(NULL==T) 14 { 15 T=new BiNode; 16 T->data=key; 17 T->lchild=T->rchild=NULL; 18 } 19 else if(T->data==key) 20 cout<<"不能重复!"; 21 else if(T->data>key) 22 insertBST(T->lchild,key); 23 else 24 insertBST(T->rchild,key); 25 26 } 27 //通过插入函数实现创建二叉排序树 28 void createBST(BiTree &T) 29 { 30 int n; 31 cout<<"请输入要插入的节点数: "; 32 cin>>n; 33 int a[n]; 34 cout<<"请输入要插入的数据:中间用空格分开"<<endl; 35 for(int i=0;i<n;i++) 36 { 37 cin>>a[i]; 38 insertBST(T,a[i]); 39 } 40 41 cout<<"创建二叉排序树完成!"<<endl; 42 43 } 44 45 //前序遍历并打印 46 void preOrderTraverse(BiTree T) 47 { 48 if(T) 49 { 50 cout <<T->data<< " "; 51 preOrderTraverse(T->lchild); 52 preOrderTraverse(T->rchild); 53 } 54 } 55 //中序遍历并打印 56 void midOrderTraverse(BiTree T) 57 { 58 59 if(T) 60 { 61 midOrderTraverse(T->lchild); 62 cout <<T->data<< " "; 63 midOrderTraverse(T->rchild); 64 } 65 } 66 67 //定义全局变量layer,表示层数 68 int layer=0; 69 //下面是查找函数,返回是否查找到数据并且可以确定查找元素的层数 70 bool searchBST(BiTree &T,int key) 71 { 72 layer++; 73 if(T==NULL) 74 { 75 return false; 76 } 77 else 78 { 79 if (key==T->data) 80 { 81 82 return true; 83 84 } 85 else if(key<T->data) 86 searchBST(T->lchild,key); 87 else 88 searchBST(T->rchild,key); 89 } 90 } 91 //利用上面查找函数实现查找操作 92 void findBST(BiTree &T) 93 { 94 int k; 95 cout<<"请输入要查找的元素值: "; 96 cin>>k; 97 if(searchBST(T,k)) 98 { 99 cout<<"查找成功,该元素位于二叉树中!"<<endl; 100 cout<<"层数为:"<<layer<<endl; 101 } 102 103 else 104 cout<<"没有查找到该元素!"<<endl; 105 }
//定义删除节点的函数 106 void deletenode(BiTree &p) 107 { 108 BiTree q,s; //函数形参P指向要删除的节点,即它的双亲节点的rchild 109 //根据要删除的节点的孩子情况分三种讨论 110 //没有左孩子 111 if(!p->lchild) 112 { 113 q=p; 114 p=p->rchild; 115 delete q; 116 } 117 //没有右孩子 118 if(!p->rchild) 119 { 120 q=p; 121 p=p->lchild; 122 delete q; 123 124 } 125 //两个孩子都有 126 else 127 { 128 q=p; //q指向上一个节点,s指向下一个节点,即指向q的右孩子,初始时q=p,最终s指向跟p节点换值的那个节点。 129 s=q->lchild; 130 131 while(s->rchild) //通过这个循环实现寻找最接近要删除节点(p)值的节点 132 { 133 q=s; 134 s=s->rchild; 135 } 136 p->data=s->data; //交换值,有个注意事项,s是不存在右孩子的,因为如果存在,则右孩子比他大,更接近p,s需要继续循环,最终s还是没有右孩子。 137 if(q!=p) 138 { 139 q->rchild=s->lchild; 140 } 141 else //如果q,s 没有移动,即此时q=p,s的初始值就是最接近p点的节点,此时q不存在右节点,需要单独讨论
142 { 143 q->lchild=s->lchild; 144 } 145 delete s; 146 } 147 148 149 } 150 151 //删除操作 152 bool deleteBST(BiTree &T,int del) 153 { 154 if(!T) 155 return false; 156 else 157 { 158 if(T->data==del) 159 { 160 deletenode(T); 161 return true; 162 } 163 else if(del<T->data) 164 { 165 return deleteBST(T->lchild,del); 166 } 167 else 168 { 169 return deleteBST(T->rchild,del); 170 } 171 } 172 173 } 174
下面是主函数:
1 //主函数 2 int main() 3 { 4 BiTree T=NULL; 5 int d; 6 createBST(T); 7 cout<<"前序遍历的结果为:"<<endl; 8 preOrderTraverse(T); 9 cout<<endl; 10 cout<<"中序遍历的结果为:"<<endl; 11 midOrderTraverse(T); 12 cout<<endl; 13 findBST(T); 14 cout<<"请输入要删除的数据:"<<endl; 15 cin>>d; 16 deleteBST(T,d); 17 cout<<"前序遍历的结果为:"<<endl; 18 preOrderTraverse(T); 19 20 }
上面的代码分别实现了查找,建立,插入和删除的操作,删除比较难主要是因为删除节点后下面的所有节点都会受到影响。此时采取的思维是分类讨论节点的孩子节点情况,
最复杂的情况是存在左右孩子,此时有两种思路,对左边孩子树进行操作或者对右边孩子树进行操作,我给出的代码是左边,二者道理一样。具体方法参考代码,说明很详细。
下面给出一个存在双孩子节点的图
画的虽然简陋,但大概意思就这样,(画图的确是理解数据结构的利器啊)最后给出控制台运行结果:
over~