二叉排序树:插入、删除、查找性能都不错,构建起来也不是很复杂,性能还很稳定的数据结构。
数组:适合查找操作 链表:适合插入和删除操作
所有的代码如下:
#include<stdio.h> #include<stdlib.h> typedef struct BiTNode{ int data; //结点数据 struct BiTNode *lchild,*rchild; //左右子树 }BiTNode,*BiTree; //二叉排序树的添加 void insertNode(BiTree &T,int key) { if(T==NULL) //如果二叉排序树为空 { T=(BiTNode*)malloc(sizeof(BiTNode)); T->data=key; T->lchild=NULL; T->rchild=NULL; } else if(key<T->data) { insertNode(T->lchild,key); //往左边走 } else if(key>T->data) { insertNode(T->rchild,key); //往右边走 } else { printf("已有该结点值得存在,无法插入 "); } } //生成二叉排序树 void createBiTree(BiTree &T,int *a,int n) { int i=0; while(i<n) { insertNode(T,a[i]); i++; } } //二叉树的查找操作 int searchBiTree(BiTree T,int key) { if(T==NULL) { return -1; } else if(key<T->data) { searchBiTree(T->lchild,key); //在左子树查找 } else if(key>T->data) { searchBiTree(T->rchild,key); //在右子树查找 } else //key==T->rchild->data { return 1; //查找成功 } } //二叉排序树的删除操作 void deleteNode(BiTree &T,int key) { //先要找到值为key的结点 if(T==NULL) { printf("无法删除该操作 "); } else if(key<T->data) { deleteNode(T->lchild,key); } else if(key>T->data) { deleteNode(T->rchild,key); } else //key==T>data 找到了该结点 { BiTree m,n;//指向结点的指针 if(T->lchild==NULL) //只有右子树 { m=T;//赋值该结点,避免指针找不到了,造成内存泄漏 T=T->rchild; //指针指向的位置发生改变 free(m); //释放该结点 } else if(T->rchild==NULL) //只有左子树 { m=T;//赋值该结点,避免指针找不到了,造成内存泄漏 T=T->lchild; //指针指向的位置发生改变 free(m); //释放该结点 } else //既有左子树也有右子树 { m=T; n=T->lchild; while(n->rchild)//找到T结点左子树的最大值 { m=n; //m是n的双亲 n是T结点左子树的最大值 n=n->rchild; } T->data=n->data; //我们不用释放该结点,我们是释放的是T结点左子树的最大值 if(m!=T) //当n是T的左子树时,m==T { m->rchild=n->lchild; } else { m->lchild=n->lchild; } free(n); } } } //二叉排序树的中序遍历 void printfSort(BiTree T) { if(T) //如果不是空树 { printfSort(T->lchild); printf("%d ",T->data); printfSort(T->rchild); } } int main() { BiTree T=NULL; //一开始的结点为空 int number; printf("请输入你要进行排序数的个数 "); scanf("%d",&number); int a[number]; printf("请依次输入序列的值 "); // 5 4 1 3 2 10 8 7 15 6 for(int i=0;i<number;i++) { scanf("%d",&a[i]); } createBiTree(T,a,number); //数组生成二叉排序树 printf("结束操作---------0 "); printf("查找操作---------1 "); printf("插入操作---------2 "); printf("删除操作---------3 "); printf("打印操作---------4 "); int n,k; //n是指令 k是数值 printf("请输入指令:"); scanf("%d",&n); while(n!=0) { switch(n) { case 0: break; case 1: //查找操作 printf("请输入你要查找的数值:"); scanf("%d",&k); if(searchBiTree(T,k)>0) { printf("查找成功 "); } else { printf("查找失败 "); } break; case 2: //插入操作 printf("请输入你要插入的数值:"); scanf("%d",&k); insertNode(T,k); break; case 3: //删除操作 printf("请输入你要删除的数值:"); scanf("%d",&k); deleteNode(T,k); break; case 4: //打印操作 printfSort(T); printf(" "); break; default: printf("你输入的指令不正确 "); } printf("请重新输入指令:"); scanf("%d",&n); } free(T); return 0; }
该程序功能已基本实现,可以正常运行
遗留的问题:删除节点操作考虑三种情况 (1)左子树为空 (2)右子树为空 (3)左右子树都不为空
但是为什么没有考虑左右子树都为空的情况,但是删除操作还是可以正常进行删除没有左右子树的结点,这是我疑惑的地方!