这个和普通的二叉树一样的
typedef struct BiTNode { DataType data; //数值 struct BiTNode* lchild; //左孩子 struct BiTNode* rchild; //右孩子 int flag; //非递归遍历时可能会使用到 } BiTNode,*BiTree; //搜索树结构体
这个相当于创建了一棵二叉搜索树
我使用了递归和迭代两种方法,迭代效率更高些,不过更臃肿些
//递归插入并返回头节点 BiTree Insert_D(BiTree root, DataType data) { if(!root)//找到了对应位置 那就插入(就是让这个空节点变成插入的这个节点)! { root = (BiTree)malloc(sizeof(BiTNode)); root->data = data; root->flag = 0; root->lchild = root->rchild = NULL; } else//没找到就继续找 { if(data < root->data) root->lchild = Insert_D(root->lchild,data);//往后面找 else root->rchild = Insert_D(root->rchild,data); } return root;//返回这一层的头节点指针 } //迭代插入并返回头节点 BiTree Insert(BiTree root, DataType data) { BiTree Faceroot,Preroot; //保存头节点 Faceroot = root; //指向前一个节点 while(root)//找到对应位置 { Preroot = root; if(data < root->data) root = root->lchild; else root = root->rchild; } root = (BiTree)malloc(sizeof(BiTNode));//给要插入的数值创建空间 root->data = data; root->flag = 0; root->lchild = root->rchild = NULL; if(!Faceroot) //用于给空树插入时返回第一个插入的节点的指针 return root; if(data < Preroot->data)//给Preroot后面插入新创建节点 Preroot->lchild = root; else Preroot->rchild = root; return Faceroot; //返回树的头节点指针 }
这里也是使用了递归和迭代,个人感觉这个的迭代更好写一些
//尾递归查找 //从root节点开始往下查找 关键值key,如果找到就返回key节点的指针,否则返回NULL BiTree Find_D(BiTree root,DataType key) { if(!root) return NULL; if(key < root->data) return Find_D(root->lchild,key); else if(key > root->data) return Find_D(root->rchild,key); else return root; } //迭代查找 //从root节点开始往下查找 关键值key,如果找到就返回key节点的指针,否则返回NULL BiTree Find(BiTree root,DataType key) { while(root) { if(root->data == key) break; else if(key < root->data) root = root->lchild; else root = root->rchild; } return root; }
这里也是两种方法,差别也不大
//从root节点开始迭代查找最小值,找到就返回其指向该节点指针,否则返回NULL BiTree FindMin(BiTree root)//最左边 { if(root) while(root->lchild) root=root->lchild; return root; } //从root节点开始迭代查找最大值,找到就返回其指向该节点指针,否则返回NULL BiTree FindMax(BiTree root)//最右边 { if(root) while(root->rchild) root=root->rchild; return root; } //递归查找最大值 BiTree FindMax_D(BiTree root) { if(!root) return NULL; if(!root->rchild) return root; return FindMax_D(root->rchild); }
这个就需要慢慢来理解一下了(手绘了一下,有亿点点丑…)
删除节点大概三种方案
第一种:
第二种:
第三种:
//删除节点 BiTree Del(BiTree root, DataType key) { if(root) { if(key < root->data) root->lchild = Del(root->lchild,key); else if(key > root->data) root->rchild = Del(root->rchild,key); else //找到要删除的点啦 { if(root->lchild&&root->rchild)//两个孩子都存在的情况 { BiTree temp = FindMin(root->rchild); //寻找右孩子里的最小值 (ps:也可以左孩子里最大值) 然后让需要被删除的点的值变成那个最小值(或者最大值),然后去删除那个最小值...递归 root->data = temp->data; root->rchild = Del(root->rchild,root->data); } else //叶子节点或者只有一个孩子的情况 { BiTree temp = root; if(root->lchild) //有左孩子就让它等于左孩子节点 root = root->lchild; else if(root->rchild) //有右孩子就让它等于右孩子节点 root = root->rchild; else //如果是叶子节点就让它为空 root = NULL; free(temp); } } } else printf("没有该节点\n"); return root;//返回节点 }
//先序遍历 void ProPrint(BiTree root)//这个的先序遍历和最开始输入的顺序是一样的,其他遍历方式可以参考之前写的文章 { if(!root) return; printf("%d ",root->data); ProPrint(root->lchild); ProPrint(root->rchild); }
#include<stdio.h> #include<stdlib.h> typedef int DataType; //自定义节点数值类型 typedef struct BiTNode { DataType data; //数值 struct BiTNode* lchild; //左孩子 struct BiTNode* rchild; //右孩子 int flag; } BiTNode,*BiTree;//搜索树结构体 //尾递归查找 //从root节点开始往下查找 关键值key,如果找到就返回key节点的指针,否则返回NULL BiTree Find_D(BiTree root,DataType key) { if(!root) return NULL; if(key < root->data) return Find_D(root->lchild,key); else if(key > root->data) return Find_D(root->rchild,key); else return root; } //迭代查找 //从root节点开始往下查找 关键值key,如果找到就返回key节点的指针,否则返回NULL BiTree Find(BiTree root,DataType key) { while(root) { if(root->data == key) break; else if(key < root->data) root = root->lchild; else root = root->rchild; } return root; } //从root节点开始迭代查找最小值,找到就返回其指向该节点指针,否则返回NULL BiTree FindMin(BiTree root)//最左边 { if(root) while(root->lchild) root=root->lchild; return root; } //从root节点开始迭代查找最大值,找到就返回其指向该节点指针,否则返回NULL BiTree FindMax(BiTree root)//最右边 { if(root) while(root->rchild) root=root->rchild; return root; } //递归查找最大值 BiTree FindMax_D(BiTree root) { if(!root) return NULL; if(!root->rchild) return root; return FindMax_D(root->rchild); } //递归插入并返回头节点 BiTree Insert_D(BiTree root, DataType data) { if(!root)//找到了对应位置 那就插入(就是让这个空节点变成插入的这个节点)! { root = (BiTree)malloc(sizeof(BiTNode)); root->data = data; root->flag = 0; root->lchild = root->rchild = NULL; } else//没找到就继续找 { if(data < root->data) root->lchild = Insert_D(root->lchild,data);//往后面找 else root->rchild = Insert_D(root->rchild,data); } return root;//返回这一层的头节点指针 } //迭代插入并返回头节点 BiTree Insert(BiTree root, DataType data) { BiTree Faceroot,Preroot; //保存头节点 Faceroot = root; //指向前一个节点 while(root)//找到对应位置 { Preroot = root; if(data < root->data) root = root->lchild; else root = root->rchild; } root = (BiTree)malloc(sizeof(BiTNode));//给要插入的数值创建空间 root->data = data; root->flag = 0; root->lchild = root->rchild = NULL; if(!Faceroot) //用于给空树插入时返回第一个插入的节点的指针 return root; if(data < Preroot->data)//给Preroot后面插入新创建节点 Preroot->lchild = root; else Preroot->rchild = root; return Faceroot; //返回树的头节点指针 } //删除节点 BiTree Del(BiTree root, DataType key) { if(root) { if(key < root->data) root->lchild = Del(root->lchild,key); else if(key > root->data) root->rchild = Del(root->rchild,key); else //找到要删除的点啦 { if(root->lchild&&root->rchild)//两个孩子都存在的情况 { BiTree temp = FindMin(root->rchild); //寻找右孩子里的最小值 (ps:也可以左孩子里最大值) 然后让需要被删除的点的值变成那个最小值(或者最大值),然后去删除那个最小值...递归 root->data = temp->data; root->rchild = Del(root->rchild,root->data); } else //叶子节点或者只有一个孩子的情况 { BiTree temp = root; if(root->lchild) //有左孩子就让它等于左孩子节点 root = root->lchild; else if(root->rchild) //有右孩子就让它等于右孩子节点 root = root->rchild; else //如果是叶子节点就让它为空 root = NULL; free(temp); } } } else printf("没有该节点\n"); return root;//返回节点 } //先序遍历 void ProPrint(BiTree root) { if(!root) return; printf("%d ",root->data); ProPrint(root->lchild); ProPrint(root->rchild); } int main() { BiTree root = NULL; printf("请输入数值来建立二叉搜索树,q停止输入:"); DataType data; while(scanf("%d",&data)==1) root = Insert(root,data); printf("二叉搜索树的先序遍历为:"); ProPrint(root); putchar('\n'); BiTree p; p = FindMax(root); if(p) printf("最大值为:%d\n",p->data); p = FindMin(root); if(p) printf("最小值为:%d\n",p->data); fflush(stdin); printf("请输入需要删除的节点的值:"); scanf("%d",&data); Del(root,data); printf("二叉搜索树的先序遍历为:");//这个和输入的顺序是一样的... ProPrint(root); return 0; }
可能会有一些地方写的不好或者有错误,如果有建议请您指出,我一定洗耳恭听,谢谢