C语言实现二叉树的搜索及相关算法示例

 更新时间:2017年06月08日 11:16:54   作者:typ2004  
这篇文章主要介绍了C语言实现二叉树的搜索及相关算法,结合具体实例形式分析了基于C语言创建、遍历、搜索等相关算法与实现技巧,需要的朋友可以参考下

本文实例讲述了C语言实现二叉树的搜索及相关算法。分享给大家供大家参考,具体如下:

二叉树(二叉查找树)是这样一类的树,父节点的左边孩子的key都小于它,右边孩子的key都大于它。

二叉树在查找和存储中通常能保持logn的查找、插入、删除,以及前驱、后继,最大值,最小值复杂度,并且不占用额外的空间。

这里演示二叉树的搜索及相关算法:

#include<stack>
#include<queue>
using namespace std;
class tree_node{
public:
  int key;
  tree_node *left;
  tree_node *right;
  int tag;
  tree_node(){
    key = 0;
    left = right = NULL;
    tag = 0;
  }
  ~tree_node(){}
};
void visit(int value){
  printf("%d\n", value);
}
// 插入
tree_node * insert_tree(tree_node *root, tree_node* node){
  if (!node){
    return root;
  }
  if (!root){
    root = node;
    return root;
  }
  tree_node * p = root;
  while (p){
    if (node->key < p->key){
      if (p->left){
        p = p->left;
      }
      else{
        p->left = node;
        break;
      }
    }
    else{
      if (p->right){
        p = p->right;
      }
      else{
        p->right = node;
        break;
      }
    }
  }
  return root;
}
// 查询key所在node
tree_node* search_tree(tree_node* root, int key){
  tree_node * p = root;
  while (p){
    if (key < p->key){
      p = p->left;
    }
    else if (key > p->key){
      p = p->right;
    }
    else{
      return p;
    }
  }
  return NULL;
}
// 创建树
tree_node* create_tree(tree_node *t, int n){
  tree_node * root = t;
  for (int i = 1; i<n; i++){
    insert_tree(root, t + i);
  }
  return root;
}
// 节点前驱
tree_node* tree_pre(tree_node* root){
  if (!root->left){ return NULL; }
  tree_node* p = root->left;
  while (p->right){
    p = p->right;
  }
  return p;
}
// 节点后继
tree_node* tree_suc(tree_node* root){
  if (!root->right){ return NULL; }
  tree_node* p = root->right;
  while (p->left){
    p = p->left;
  }
  return p;
}
// 中序遍历
void tree_walk_mid(tree_node *root){
  if (!root){ return; }
  tree_walk_mid(root->left);
  visit(root->key);
  tree_walk_mid(root->right);
}
// 中序遍历非递归
void tree_walk_mid_norecursive(tree_node *root){
  if (!root){ return; }
  tree_node* p = root;
  stack<tree_node*> s;
  while (!s.empty() || p){
    while (p){
      s.push(p);
      p = p->left;
    }
    if (!s.empty()){
      p = s.top();
      s.pop();
      visit(p->key);
      p = p->right;
    }
  }
}
// 前序遍历
void tree_walk_pre(tree_node *root){
  if (!root){ return; }
  visit(root->key);
  tree_walk_pre(root->left);
  tree_walk_pre(root->right);
}
// 前序遍历非递归
void tree_walk_pre_norecursive(tree_node *root){
  if (!root){ return; }
  stack<tree_node*> s;
  tree_node* p = root;
  s.push(p);
  while (!s.empty()){
    tree_node *node = s.top();
    s.pop();
    visit(node->key);
    if (node->right){
      s.push(node->right);
    }
    if (node->left){
      s.push(node->left);
    }
  }
}
// 后序遍历
void tree_walk_post(tree_node *root){
  if (!root){ return; }
  tree_walk_post(root->left);
  tree_walk_post(root->right);
  visit(root->key);
}
// 后序遍历非递归
void tree_walk_post_norecursive(tree_node *root){
  if (!root){ return; }
  stack<tree_node*> s;
  s.push(root);
  while (!s.empty()){
    tree_node * node = s.top();
    if (node->tag != 1){
      node->tag = 1;
      if (node->right){
        s.push(node->right);
      }
      if (node->left){
        s.push(node->left);
      }
    }
    else{
      visit(node->key);
      s.pop();
    }
  }
}
// 层级遍历非递归
void tree_walk_level_norecursive(tree_node *root){
  if (!root){ return; }
  queue<tree_node*> q;
  tree_node* p = root;
  q.push(p);
  while (!q.empty()){
    tree_node *node = q.front();
    q.pop();
    visit(node->key);
    if (node->left){
      q.push(node->left);
    }
    if (node->right){
      q.push(node->right);
    }
  }
}
// 拷贝树
tree_node * tree_copy(tree_node *root){
  if (!root){ return NULL; }
  tree_node* newroot = new tree_node();
  newroot->key = root->key;
  newroot->left = tree_copy(root->left);
  newroot->right = tree_copy(root->right);
  return newroot;
}
// 拷贝树
tree_node * tree_copy_norecursive(tree_node *root){
  if (!root){ return NULL; }
  tree_node* newroot = new tree_node();
  newroot->key = root->key;
  stack<tree_node*> s1, s2;
  tree_node *p1 = root;
  tree_node *p2 = newroot;
  s1.push(root);
  s2.push(newroot);
  while (!s1.empty()){
    tree_node* node1 = s1.top();
    s1.pop();
    tree_node* node2 = s2.top();
    s2.pop();
    if (node1->right){
      s1.push(node1->right);
      tree_node* newnode = new tree_node();
      newnode->key = node1->right->key;
      node2->right = newnode;
      s2.push(newnode);
    }
    if (node1->left){
      s1.push(node1->left);
      tree_node* newnode = new tree_node();
      newnode->key = node1->left->key;
      node2->left = newnode;
      s2.push(newnode);
    }
  }
  return newroot;
}
int main(){
  tree_node T[6];
  for (int i = 0; i < 6; i++){
    T[i].key = i*2;
  }
  T[0].key = 5;
  tree_node* root = create_tree(T, 6);
  //tree_walk_mid(root);
  //tree_walk_mid_norecursive(root);
  //tree_walk_pre(root);
  //tree_walk_pre_norecursive(root);
  //tree_walk_post(root);
  //tree_walk_post_norecursive(root);
  //tree_walk_level_norecursive(root);
  visit(search_tree(root, 6)->key);
  visit(tree_pre(root)->key);
  visit(tree_suc(root)->key);
  //tree_node* newroot = tree_copy_norecursive(root);
  //tree_walk_mid(newroot);
  return 0;
}

希望本文所述对大家C语言程序设计有所帮助。

相关文章

  • 浅谈do {...} while (0) 在宏定义中的作用

    浅谈do {...} while (0) 在宏定义中的作用

    下面小编就为大家带来一篇浅谈do {...} while (0) 在宏定义中的作用。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • 使用OpenCV实现检测和追踪车辆

    使用OpenCV实现检测和追踪车辆

    这篇文章主要为大家详细介绍了使用OpenCV实现检测和追踪车辆,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • C语言实现单词小助手功能完善版

    C语言实现单词小助手功能完善版

    这篇文章主要为大家详细介绍了C语言实现单词小助手功能的完善版,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-10-10
  • OpenCV利用背景建模检测运动物体

    OpenCV利用背景建模检测运动物体

    这篇文章主要为大家详细介绍了OpenCV利用背景建模检测运动物体,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • C++读写.mat文件的方法

    C++读写.mat文件的方法

    本文介绍了“C++读写.mat文件的方法”,需要的朋友可以参考一下
    2013-03-03
  • C++中指针的数据类型和运算相关知识小结

    C++中指针的数据类型和运算相关知识小结

    这篇文章主要介绍了C++中指针的数据类型和运算相关知识小结,是C++入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • C++对象排序的比较你了解吗

    C++对象排序的比较你了解吗

    这篇文章主要为大家详细介绍了C++对象排序的比较,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • C++ Vector用法深入剖析

    C++ Vector用法深入剖析

    C++ Vector应用方式是比较特殊的,我们将会在这篇文章中针对于它的应用方式进行一个详细的介绍,希望大家能充分掌握这一应用技巧
    2014-08-08
  • C++17新特性个人总结

    C++17新特性个人总结

    这篇文章主要介绍了C++17新特性个人总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • C语言如何利用ASCII码表统计字符串每个字符出现的次数

    C语言如何利用ASCII码表统计字符串每个字符出现的次数

    这篇文章主要介绍了C语言如何利用ASCII码表统计字符串每个字符出现的次数,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01

最新评论