zoukankan      html  css  js  c++  java
  • 排序二叉树的实现和我的一个数据结构设计

    一。基本概念

    二叉排序树又称二叉搜索树,即在树的任何一个结点,都满足左子树小于根,根小于右子树。排序二叉树可以作为Map的关键码。主要的作用是快速的查找(相当于二分法)

    二。基本算法

    1.查找

    查找时,首先和根结点对比,若相等,则查找成功。若大于根,则再向右子树查找;如果小于根,则向根的左子树查找;依次类推,直到查找成功或者遇到空结点。

    2.插入

    找到要插入的位置,类似于上面查找的方式,将新结点插入到查找到的左子树或者右子树。

    3.删除

    1.当要删除结点不存在左子树,直接将要删除结点的右子树赋给要删除点的父结点的相应子结点

    2.当要删除的结点存在左子树,在此结点的左子树中,查找到关键码最大的一个结点r,将r的右指针指要要删除点的右子树,用要删除点的左子树代替要删除点

    三。具体代码

     声明

    View Code
     1 template<class KEY> 
    2 class BinSearchTree
    3 {
    4 public:
    5 BinSearchTree(KEY k)
    6 {
    7 llink = NULL;
    8 rlink = NULL;
    9 key = k;
    10 }
    11 public:
    12 KEY key;
    13 BinSearchTree* llink;
    14 BinSearchTree* rlink;
    15
    16
    17 int search(KEY key,BinSearchTree<KEY>** position);
    18 int insert(KEY key);
    19 int delete_node(KEY key);
    20 };

     实现

    View Code
     1 template<class KEY>
    2 int BinSearchTree<KEY>::search(KEY key,BinSearchTree<KEY>** pos)
    3 {
    4 BinSearchTree* p = this;
    5
    6
    7 while(p){
    8 *pos = p;
    9 if(p->key == key){
    10 *pos = p;
    11 return 1;
    12 }
    13 else if(p->key > key ){
    14 p = p->llink;
    15 }
    16 else{
    17 p = p->rlink;
    18 }
    19 }
    20
    21 return 0;
    22 }
    23 template<class KEY>
    24 int BinSearchTree<KEY>::insert(KEY key)
    25 {
    26 BinSearchTree* pos = NULL;
    27 if(search(key,&pos) == 1){
    28 return -1;//查找到相同的key
    29 }
    30 BinSearchTree* p = new BinSearchTree(key);
    31 //如果pos null,说明是空树
    32 if(!pos){
    33 pos = p;
    34 }
    35 else if( pos->key > key ){
    36 pos->llink = p;
    37 }
    38 else{
    39 pos->rlink = p;
    40 }
    41
    42 return 0;
    43 }
    44 template<class KEY>
    45 int BinSearchTree<KEY>::delete_node(KEY key)
    46 {
    47 BinSearchTree* p = this; //需要查找的结点
    48 BinSearchTree* parent = NULL; //要查找的点的父结点
    49
    50 while(p){
    51 if( key == p->key ){
    52 break;
    53 }
    54 parent = p;//在向下个结点遍历前,将本结点设置为父结点
    55
    56 if( key > p->key ){
    57 p = p->rlink;
    58 }
    59 else{
    60 p = p->llink;
    61 }
    62 }
    63 if( !p ){
    64 return -1;
    65 }
    66
    67 //1.如果没有左子树,则直接被删除结点用右子树代替
    68 if(!p->llink){
    69 if(parent->llink == p){
    70 parent->llink = p->rlink;
    71 }
    72 else if(parent->rlink == p){
    73 parent->rlink = p->rlink;
    74 }
    75 delete p;
    76 return 0;
    77 }
    78 //2.如果有有左子树,则找到左子树里最大的结点,将其右子树设置成要查找的子树的右子树。并将欲查找的子树用它的左子树代替
    79 BinSearchTree* r = NULL;//r为要查找的结点的左子树的最远端右子树
    80 r = p->llink;
    81 while(r->rlink)r = r->rlink;
    82
    83 r->rlink = p->rlink;
    84
    85 if(parent->llink == p){
    86 parent->llink = p->llink;
    87 }
    88 else if(parent->rlink == p){
    89 parent->rlink = p->llink;
    90 }
    91
    92
    93 }

    四。我的新设计

    1.使用一个顺序结构存储(比如数组)实际对象 假设叫做list

    2.使用一个二叉排序树tree存储list中存储的元素(每个元素是一个对象)的指针或者引用。

    3.每次对list添加,删除时,对tree都要做相应的操作

    优点:

    相当于实现了一个简单的map,可以使用两种方式定位数据对象。比如游戏中存储玩家类,大部分时间是通过id取得玩家对象的,即通过list(索引号)的方式,但同时也可能存在使用名字取得玩家对象的情况,可以把名字存在tree中。tree只是list的一个数据映射,耗费较少的内存。当然,直接使用map<名字,索引号>的方式也是可以的。

    还有一个优点是可以比较方便的查找到最大和最小值。

    缺点:

    不能插入重复的数据。

    缺点:

  • 相关阅读:
    #419 Div2 Problem B Karen and Coffee (统计区间重叠部分 && 前缀和)
    #418 Div2 Problem B An express train to reveries (构造 || 全排列序列特性)
    FZU 2203 单纵大法好 (二分 && 贪心)
    51Nod 1413 权势二进制 (思维)
    51Nod 1433 0和5 (数论 && 被9整除数的特点)
    POJ 2492 A Bug's Life (带权并查集 && 向量偏移)
    POJ 1456 Supermarket (贪心 && 并查集优化)
    POJ 1182 食物链 (带权并查集 && 向量偏移)
    #417 Div2 Problem B Sagheer, the Hausmeister (DFS && 枚举)
    #417 Div2 Problem C Sagheer and Nubian Market (二分 && std::accumulate)
  • 原文地址:https://www.cnblogs.com/fox7nights/p/2319665.html
Copyright © 2011-2022 走看看