前面总结了顺序查找,二分查找,分块查找算法,此篇博文将详解介绍二叉排序算法(Binary Sort Tree)。

在介绍二叉排序算法之前,首先介绍什么事二叉排序树(BST)。

首先从二叉树讲起:

1、二叉树的概念

二叉树是每个结点最多有两个子树的有序树。通常子树的根被称作“左子树”(leftsubtree)和“右子树”(rightsubtree)。二叉树常被用作二叉查找树和二叉堆或是二叉排序树。二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2的 i -1次方个结点;深度为k的二叉树至多有2^(k) -1个结点;对任何一棵二叉树T,如果其终端结点数(即叶子结点数)为n0,度为2的结点数为n2,则n0 = n2 +1。

二叉树的链式存储结构是一类重要的数据结构,其形式定义如下:

//二叉树结点
typedef struct BiTNode{  //数据  char data;  //左右孩子指针  struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;

2、二叉树的建立

通过读入一个字符串,建立二叉树的算法如下:

//按先序序列创建二叉树
int CreateBiTree(BiTree &T){  char data;  //按先序次序输入二叉树中结点的值(一个字符),‘#’表示空树  scanf("%c",&data);  if(data == '#'){  T = NULL;  }  else{  T = (BiTree)malloc(sizeof(BiTNode));  //生成根结点  T->data = data;  //构造左子树  CreateBiTree(T->lchild);  //构造右子树  CreateBiTree(T->rchild);  }  return 0;
}

3、二叉树的遍历

遍历是对树的一种最基本的运算,所谓遍历二叉树,就是按一定的规则和顺序走遍二叉树的所有结点,使每一个结点都被访问一次,而且只被访问一次。由于二叉树是非线性结构,因此,树的遍历实质上是将二叉树的各个结点转换成为一个线性序列来表示。

先序遍历:访问根节点,访问左子节点,访问右子节点

中序遍历:访问左子结点,访问根节点,访问右子节点

后序遍历:访问左子节点,访问右子节点,访问根节点

层次遍历:从顶层到底层,按从顶向下,从左至右的顺序来逐层访问每个节点,层次遍历的过程中需要用队列。

事实上,知道任意两种方式,并不能唯一地确定树的结构,但是,只要知道中序遍历和另外任意一种遍历方式,就一定可以唯一地确定一棵树。

// 先序遍历
void preOrderTraverse(BST T)
{if(T){cout << T->key <<" ";preOrderTraverse(T->lChild);preOrderTraverse(T->rChild);}
}// 中序遍历
void inOrderTraverse(BST T)
{if(T){inOrderTraverse(T->lChild);cout << T->key <<" ";inOrderTraverse(T->rChild);}
}//后序遍历
void postOrderTraverse(BST T)
{if(T){postOrderTraverse(T->lChild);postOrderTraverse(T->rChild);cout << T->key <<" ";}
}
//层次遍历
void LevelOrder(BST T)
{BST p = T;//队列queue<BST> queue;queue.push(p);while(!queue.empty()){p = queue.front();cout<< p->key<<" ";queue.pop();if(p->lChild != NULL)queue.push(p->lChild);if(p->rChild != NULL)queue.push(p->rChild);}
}

4.BST树的概念

它或者是一棵空树;或者是具有下列性质的二叉树:

  (1)若左子树不空,则左子树上所有结点的值均小于左子树所在树的根结点的值;

  (2)若右子树不空,则右子树上所有结点的值均大于右子树所在树的根结点的值;

  (3)左、右子树也分别为二叉排序树;

最大关键字及最小关键字元素:顾名思义,肯定是二叉搜索树的最大最小值,以最大关键字为例,一直查询树的右孩子,直到该节点无右孩子为止,该节点就是最大关键字, 当然,最小关键字同理;

后继与前驱:对一个节点来说,最大的小于该节点值的即是前驱,最小的大于该节点        值的即是后继。以后继为例,如果该节点的右子树不为空,那么后继就是右子树中最小关键字元素;若是该节点右孩子不存在,这时,只需由该节点往上寻找,直到这个节点是其   父节点的左孩子即可。当然,前驱也是类似情况;

5、BST树的查找:

时间复杂度与树的深度的有关,O(log n)。

  步骤:若根结点的关键字值等于查找的关键字,成功。

  否则:若小于根结点的关键字值,递归查左子树。

  若大于根结点的关键字值,递归查右子树。

  若子树为空,查找不成功。

6、BST树的插入

首先执行查找算法,找出被插结点的父亲结点。

  判断被插结点是其父亲结点的左儿子还是右儿子。将被插结点作为叶子结点插入。

  若二叉树为空。则首先单独生成根结点。

  注意:新插入的结点总是叶子结点,所以算法复杂度是O(h)。

BST树的建立过程就是依次插入的过程。

7、BST树的删除

  如果删除的结点没有孩子,则删除后算法结束;

  如果删除的结点只有一个孩子,则删除后该孩子取代被删除结点的位置;

  如果删除的结点有两个孩子,则选择该结点的后继结点(该结点右孩子为根的树中的左   子树中的值最小的点)作为新的根,同时在该后继结点开始,递归执行删除算法,直到叶    子节点,删除算法结束。

将BST的实现写到BST.h文件中

#include <iostream>
#include <queue>
using namespace std;// BST的结点
typedef int ElemType;
typedef struct node
{  ElemType key;  struct node *lChild, *rChild;
}Node, *BST; //在BST树中插入
bool BSTInsert(BST & root, ElemType x)
{if(root == NULL){root = new Node;root->key = x;root->lChild = NULL;root->rChild = NULL;return true;}if(root->key == x)return false;if(x < root->key)return BSTInsert(root->lChild , x);return BSTInsert(root->rChild,x);
}//创建BST树
void createBST(BST &root, ElemType *x, int N)
{root = NULL;for(int i = 0; i < N; i++){BSTInsert(root,x[i]);}
}// 先序遍历
void preOrderTraverse(BST T)
{if(T){cout << T->key <<" ";preOrderTraverse(T->lChild);preOrderTraverse(T->rChild);}
}// 中序遍历
void inOrderTraverse(BST T)
{if(T){inOrderTraverse(T->lChild);cout << T->key <<" ";inOrderTraverse(T->rChild);}
}//后序遍历
void postOrderTraverse(BST T)
{if(T){postOrderTraverse(T->lChild);postOrderTraverse(T->rChild);cout << T->key <<" ";}
}
//层次遍历
void LevelOrder(BST T)
{BST p = T;//队列queue<BST> queue;queue.push(p);while(!queue.empty()){p = queue.front();cout<< p->key<<" ";queue.pop();if(p->lChild != NULL)queue.push(p->lChild);if(p->rChild != NULL)queue.push(p->rChild);}
}//查找元素,递归算法,找到返回关键字的结点指针,没找到返回NULL
BST BSTSearch(BST root, ElemType key)//递归算法
{if(root == NULL)return NULL;if(root->key == key)return root;if(key > root->key )return BSTSearch(root->rChild , key);elsereturn BSTSearch(root->lChild , key);
}//查找元素,非递归算法
BST BSTSearch2(BST root, ElemType key)
{if(root == NULL)return NULL;BST p = root;while (p->key != key){if(key < p->key)p = p->lChild;elsep = p->rChild;if(p == NULL)return NULL;}return p;
}//查找最小关键字,空树时返回NULL
BST SearchMin(BST root)
{  if(root == NULL)  return root;  while(root->lChild != NULL)  root = root->lChild;  return root;
}  //查找最大关键字,空树时返回NULL
BST SearchMax(BST root)
{  if(root == NULL)  return root;  while(root->rChild != NULL) //迭代  root = root->rChild;  return root;
} //查找前驱,即左子树中比当前数小的最大的数,若不存在左子树,复杂,暂时没有实现
BST SearchPredecessor(BST root)
{if(root == NULL)return root;//若存在左孩子,前驱是其左子树中最大的 if(root->lChild != NULL)return SearchMax(root->lChild);//不存在左孩子,需要回溯找到它的parent,因此需要在sruct中加入一个parent//   BST y = root->parent;  //while(y != NULL && root == y->lChild)  //   {  //       root = y;  //       y = root->parent;  //   }  //   return y;
}//查找后继
BST SearchSuccessor(BST root)
{  if(root == NULL)  //空  return root;  //若存在右孩子,后继是其右子树中最小的  if(root->rChild != NULL)  return SearchMin(root->rChild);  //   BST y = root->parent;  //while(y != NULL && root == y->rChild)  //   {  //       root = y;  //       y = root->parent;  //   }  //   return y;
}
BST BSTDelete(BST root, ElemType key)
{BST p,q;if(root==NULL)return root;if(root->key == key){if(root->lChild == NULL && root->rChild == NULL){free(root);return NULL;}else if(root->lChild == NULL){p = root->rChild;free(root);return p;}else if(root->rChild == NULL){p = root->lChild;free(root);return p;}else{p = q = root->rChild;while(p->lChild!=NULL)p = p->lChild;p->lChild = root->lChild;free(root);return(q);}}  if(root->key > key && root->lChild !=NULL)root->lChild = BSTDelete(root->lChild,key);if(root->key < key && root->rChild !=NULL)root->rChild = BSTDelete(root->rChild,key);return root;
}

文章参考了_Luffy的文章:http://blog.csdn.net/xjm199/article/details/20003045

以及另一位的文章:http://www.open-open.com/bbs/view/1410494404789

完整代码下载点击:

查找算法代码C++——包括顺序、二分、BST、哈希

http://download.csdn.net/detail/u010025211/8841123

查找算法系列之复杂算法:二叉排序树BST相关推荐

  1. 查找算法系列之复杂算法:哈希查找

    查找算法系列之复杂算法:哈希查找 眼下为止已经介绍了顺序查找.二分查找.分块查找.二叉排序树.见作者之前的文章: http://blog.csdn.net/u010025211/article/det ...

  2. 【算法系列】卡尔曼滤波算法

    系列文章目录 ·[算法系列]卡尔曼滤波算法 ·[算法系列]非线性最小二乘求解-直接求解法 ·[算法系列]非线性最小二乘求解-梯度下降法 ·[算法系列]非线性最小二乘-高斯牛顿法 ·[算法系列]非线性最 ...

  3. 分治法的关键特征_算法系列之常用算法之一----分治算法

    一.基本概念 在计算机科学中,分治法是一种很重要的算法.分治算法,字面上的解释是"分而治之",分治算法主要是三点: 1.将一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问 ...

  4. 排序算法系列:归并排序算法

    概述 上一篇我们说了一个非常简单的排序算法--选择排序.其复杂程序完全是冒泡级的,甚至比冒泡还要简单.今天要说的是一个相对比较复杂的排序算法--归并排序.复杂的原因不仅在于归并排序分成了两个部分进行解 ...

  5. 算法系列教程04 - 算法相关的基础概念

    本系列前面两篇讲的都是一些背景知识,从这一篇开始我们正式讲算法,从算法的一些基本概念讲起. 什么是算法 通过上一篇对图灵机原理的讲解,我们知道,一个计算问题描述的是输入/输出之间的关系,如果根据给定的 ...

  6. 【匈牙利算法】【二分图匹配】【转载】趣写算法系列之--匈牙利算法

    转载自:http://blog.csdn.net/dark_scope/article/details/8880547 [书本上的算法往往讲得非常复杂,我和我的朋友计划用一些简单通俗的例子来描述算法的 ...

  7. 趣写算法系列之--匈牙利算法

    [书本上的算法往往讲得非常复杂,我和我的朋友计划用一些简单通俗的例子来描述算法的流程] 匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思 ...

  8. python按hash分组_Python算法系列-哈希算法

    哈希算法又称散列函数算法,是一种查找算法.就是把一些复杂的数据通过某种映射关系.映射成更容易查找的方式,但这种映射关系可能会发生多个关键字映射到同一地址的现象,我们称之为冲突.在这种情况下,我们需要对 ...

  9. 排序算法系列:插入排序算法

    概述 直接插入排序(Straight Insertion Sort)的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的.记录数增1的有序表. – <大话数据结构> 版权说明 ...

最新文章

  1. “你写的 Bug 让我来改好吗” | 每日趣闻
  2. php小偷程序原理分析2
  3. zune linux_快速提示:在出售Zune HD之前,先擦除所有内容
  4. [css] 在实际编写css中你有遇到过哪些浏览器兼容性的问题?怎么解决的?
  5. led拼接屏报价_LED拼接屏的装饰
  6. 辽宁省计算机专业A类,辽宁省中职升高职招生考试计算机及应用专业综合课试卷(共2份)...
  7. 手机运行内存6+128跟8+128有什么区别?
  8. GAMES101-现代计算机图形学入门-闫令琪——Lecture 12 Geometry 3 学习笔记
  9. WebView加载淘宝,天猫链接失败
  10. Play on Words
  11. 电脑共享问题—工作组里看不到其他的WIN10主机
  12. 宝塔服务器性能跑分排行榜(CPU/内存/系统)
  13. 如何利用计算机处理,旧电脑如何处理?去卖回收教你几招!榨干闲置电脑最后一丝价值!...
  14. 【NI Multisim 14.0原理图设计基础——放置元器件】
  15. 不可不说的Java“锁”事 - 美团技术团队
  16. 申请美国计算机科学硕士,如何转专业申请美国计算机科学硕士?
  17. windows上交叉编译linux可执行文件
  18. PHP实现RSA与RSA256加密,解密,加签,验签
  19. 国内外的自学web前端开发教程网站
  20. uniapp开发小程序map上添加搜索框

热门文章

  1. c语言8255控制流水灯程序,8255LED流水灯控制.doc
  2. 爬虫批量保存网页html,2分钟带你学会网络爬虫:Excel批量爬取网页数据(详细图文版)...
  3. code-server+docker安装教程(github)
  4. Android6.0运行时权限解决方案
  5. STM32学习记录0011——AD转换
  6. 武夷学院计算机网络系统,武夷学院计算机网络王超帅实验报告双绞线的制作与测试.doc...
  7. 制作IEC101/104报文解析工具
  8. Python爬虫教程-总纲
  9. Java基础篇自然排序和定制排序
  10. 澳洲python培训