数据结构中二叉树的基本操作

开发 架构
笔者近日受人所托,搞了点二叉树的程序,顺便回顾了下二叉树的一些基本知识,特此总结。

二叉树的基本操作,可能包括:

创建,遍历,转化,复制,删除等。

遍历:前中后三种顺序的遍历,已经是各数据结构与算法教程的最基础内容,在此不重复。

创建:大多数据结构教程当中的二叉树创建程序,都是采用的递归方式,递归方式创建的二叉树与遍历的过程相似,所创建的二叉树,也是采用左右子节点方式,后续进行遍历操作十分方便。

转化:直觉上,最简单的二叉树存储方式其实是如下图的数组:

 

*此图出自某高校数据结构ppt,但实在难以查证是哪个学校,无法直接感谢,请谅解。

首先,提供个满二叉树大小的数组,然后其中数值按完全二叉树存储。

显然,此种顺序存储方法:第i号(这里编号指对应的完全二叉树的位序)结点的左右孩子一定保存在第2i及2i+1号单元中。

故此,为兼顾存储的直观与遍历等操作的方便,从顺序数组向左右子节点存储方式的转化也就十分重要。

1-转化方法

分为几个步骤:

(1)准备原始数组

(2)分析数组中的有效值,对应二叉树节点非空;

(3)创建二叉树节点;

(4)计算除最后一层子节点外,构造节点间父子关系时的循环次数;

(5)构造二叉树节点间的父子关系;

(6)确实二叉树根节点;

主要代码:

(1)准备原始数组

  1. //原始数组 
  2.     int intBiTreeInit[ARR_COUNT]; 
  3.  
  4.     
  5.     //初始化原始数组至无效值 
  6.     for(int i=0;i<=ARR_COUNT-1;i++) 
  7.         intBiTreeInit[i]=NVALUE; 
  8.  
  9.     //本if条件确保ARR_COUNT是否是的乘方-1 
  10.     if(0==(ARR_COUNT & (ARR_COUNT+1))) 
  11.     { 
  12.         for(int i=0;i<=ARR_COUNT-1;i++) 
  13.             intBiTreeInit[i]=2*(i+1); 
  14.     } 
  15.     else 
  16.         return RET_ERR; 
  17.  
  18.     //使最后两数为无效值 
  19.     intBiTreeInit[ARR_COUNT-1]=NVALUE; 
  20.     intBiTreeInit[ARR_COUNT-2]=NVALUE; 

(2)分析数组中的有效值

  1. //开始获得数组中有效值位置 
  2.    int intRel=0; 
  3.    int intArr=0; 
  4.    for(intArr=0;intArr<=intCount-1;intArr++) 
  5.    { 
  6.        if(elemArr[intArr]!=elemNValue) 
  7.        { 
  8.            intRel++; 
  9.            vecIntEffPos.push_back(intArr); 
  10.        } 
  11.        } 

(3)创建二叉树节点 

  1. //数组中有效值对应创建节点 
  2. //同时初始化父子节点为NULL 
  3. for(intArr=0;intArr<=intRel-1;intArr++) 
  4.     pBiTreeTemp=(PBiTreeNode)malloc(sizeof(BiTreeNode));; 
  5.      
  6.     if(NULL==pBiTreeTemp)                                //判断是否有足够的内存空间 
  7.     { 
  8.         cout<<"Memory alloc failure"<<endl; 
  9.         return RET_ERR; 
  10.     } 
  11.  
  12.     //将有效值赋予节点 
  13.     pBiTreeTemp->BiTreeData=elemArr[vecIntEffPos[intArr]]; 
  14.      
  15.     //初始化左右子节点为null,便于后续的遍历 
  16.     pBiTreeTemp->leftChild=NULL; 
  17.     pBiTreeTemp->rightChild=NULL; 
  18.  
  19.     //先存节点值 
  20.     vecPBiTree.push_back(pBiTreeTemp); 
(4)计算除最后一层子节点外,构造节点间父子关系时的循环次数

    //生成父子关系时最后一层不必遍历,故理论循环上限可优化 

  1. int intSubLast=0; 
  2.    intSubLast=intCount-(intCount+1)/2; 

(5)构造二叉树节点间的父子关系

  1. for(intArr=0;intArr<=intSubLast-1;intArr++) 
  2.     //左右节点若存储有效值则同时创建父子关系 
  3.     if(elemArr[intArr*2+1]!=elemNValue) 
  4.         vecPBiTree[intArr]->leftChild=vecPBiTree[intArr*2+1]; 
  5.          
  6.     if(elemArr[intArr*2+2]!=elemNValue) 
  7.         vecPBiTree[intArr]->rightChild=vecPBiTree[intArr*2+2]; 

(6)确实二叉树根节点

  1. pBiTree=vecPBiTree[0]; 

转化为左右子节点方式存储后,则各种遍历操作按大多数教程的常规方式处理即可,如前序遍历函数:

  1. int BiTreePreTrace(PBiTreeNode &pBiTree) 
  2.     //条件为非空树 
  3.     if(pBiTree) 
  4.     { 
  5.         cout<<"Node value="<<(pBiTree->BiTreeData)<<endl; 
  6.          
  7.         BiTreePreTrace(pBiTree->leftChild);    //遍历左子树 
  8.         BiTreePreTrace(pBiTree->rightChild);    //遍历右子树 
  9.     } 
  10.     return RET_OK; 

完整程序,请见附件文件。

 http://files.cnblogs.com/vbspine/cnsDSExec.rar

*上述程序在Windows7x64,VS2008环境编译运行通过

原文链接:http://www.cnblogs.com/vbspine/archive/2013/01/30/bitree.html

 

【编辑推荐】

  1. C# 4.0新特性dynamic作用浅析
  2. Visual C# 2010新特性之dynamic类型
  3. C#实例讲解二叉树原理与实现

 

责任编辑:彭凡 来源: 博客园
相关推荐

2021-04-19 07:47:42

数据结构二叉树Tree

2021-04-20 08:37:14

数据结构二叉树

2021-04-28 20:12:27

数据结构创建

2020-11-02 09:15:47

算法与数据结构

2021-01-07 08:12:47

数据结构二叉树

2021-04-01 10:34:18

Java编程数据结构算法

2020-04-27 07:05:58

二叉树左子树右子树

2021-03-19 10:25:12

Java数据结构算法

2020-09-23 18:25:40

算法二叉树多叉树

2018-03-15 08:31:57

二叉树存储结构

2021-03-22 09:00:22

Java数据结构算法

2019-08-22 09:22:44

数据结构二叉搜索树

2022-10-26 23:58:02

二叉树数组算法

2013-07-15 16:35:55

二叉树迭代器

2021-03-17 08:19:22

二叉树LeetCode

2021-08-27 11:36:44

二叉树回溯节点

2021-09-29 10:19:00

算法平衡二叉树

2021-05-06 17:46:30

二叉树数据结构

2023-04-06 07:39:48

2021-10-12 09:25:11

二叉树树形结构
点赞
收藏

51CTO技术栈公众号