二叉树的简单介绍

关于二叉树的介绍请看这里 :

二叉树的简单介绍 http://www.cnblogs.com/JiYF/p/7048785.html


二叉链表存储结构:

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。

通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址。其结点结构为:

其中,data域存放某结点的数据信息;lchild与rchild分别存放指向左孩子和右孩子的指针,当左孩子或右孩子不存在时,相应指针域值为空(用符号∧或NULL表示)。利用这样的结点结构表示的二叉树的链式存储结构被称为二叉链表,如图5-8所示。

C#实现代码

二叉树的节点类:

 Binary Tree

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DataStructure
{
/// <summary>
/// 二叉链表结点类
/// </summary>
/// <typeparam name="T"></typeparam>
public class TreeNode<T>
{
private T data; //数据域
private TreeNode<T> lChild; //左孩子 树中一个结点的子树的根结点称为这个结点的孩子
private TreeNode<T> rChild; //右孩子 public TreeNode(T val, TreeNode<T> lp, TreeNode<T> rp)
{
data = val;
lChild = lp;
rChild = rp;
} public TreeNode(TreeNode<T> lp, TreeNode<T> rp)
{
data = default(T);
lChild = lp;
rChild = rp;
} public TreeNode(T val)
{
data = val;
lChild = null;
rChild = null;
} public TreeNode()
{
data = default(T);
lChild = null;
rChild = null;
} public T Data
{
get { return data; }
set { data = value; }
} public TreeNode<T> LChild
{
get { return lChild; }
set { lChild = value; }
} public TreeNode<T> RChild
{
get { return rChild; }
set { rChild = value; }
} }
定义索引文件结点的数据类型
  /// <summary>
/// 定义索引文件结点的数据类型
/// </summary>
public struct indexnode
{
int key; //键
int offset; //位置
public indexnode(int key, int offset)
{
this.key = key;
this.offset = offset;
} //键属性
public int Key
{
get { return key; }
set { key = value; }
}
//位置属性
public int Offset
{
get { return offset; }
set { offset = value; }
} } public class LinkBinaryTree<T>
{
private TreeNode<T> head; //头引用 public TreeNode<T> Head
{
get { return head; }
set { head = value; }
} public LinkBinaryTree()
{
head = null;
} public LinkBinaryTree(T val)
{
TreeNode<T> p = new TreeNode<T>(val);
head = p;
} public LinkBinaryTree(T val, TreeNode<T> lp, TreeNode<T> rp)
{
TreeNode<T> p = new TreeNode<T>(val, lp, rp);
head = p;
} //判断是否是空二叉树
public bool IsEmpty()
{
if (head == null)
return true;
else
return false;
} //获取根结点
public TreeNode<T> Root()
{
return head;
} //获取结点的左孩子结点
public TreeNode<T> GetLChild(TreeNode<T> p)
{
return p.LChild;
} public TreeNode<T> GetRChild(TreeNode<T> p)
{
return p.RChild;
} //将结点p的左子树插入值为val的新结点,原来的左子树称为新结点的左子树
public void InsertL(T val, TreeNode<T> p)
{
TreeNode<T> tmp = new TreeNode<T>(val);
tmp.LChild = p.LChild;
p.LChild = tmp;
} //将结点p的右子树插入值为val的新结点,原来的右子树称为新节点的右子树
public void InsertR(T val, TreeNode<T> p)
{
TreeNode<T> tmp = new TreeNode<T>(val);
tmp.RChild = p.RChild;
p.RChild = tmp;
} //若p非空 删除p的左子树
public TreeNode<T> DeleteL(TreeNode<T> p)
{
if ((p == null) || (p.LChild == null))
return null;
TreeNode<T> tmp = p.LChild;
p.LChild = null;
return tmp;
} //若p非空 删除p的右子树
public TreeNode<T> DeleteR(TreeNode<T> p)
{
if ((p == null) || (p.RChild == null))
return null;
TreeNode<T> tmp = p.RChild;
p.RChild = null;
return tmp;
} //编写算法 在二叉树中查找值为value的结点 public TreeNode<T> Search(TreeNode<T> root, T value)
{
TreeNode<T> p = root;
if (p == null)
return null;
if (!p.Data.Equals(value))
return p;
if (p.LChild != null)
{
return Search(p.LChild, value);
}
if (p.RChild != null)
{
return Search(p.RChild, value);
}
return null;
} //判断是否是叶子结点
public bool IsLeaf(TreeNode<T> p)
{
if ((p != null) && (p.RChild == null) && (p.LChild == null))
return true;
else
return false;
} //中序遍历
//遍历根结点的左子树->根结点->遍历根结点的右子树
public void inorder(TreeNode<T> ptr)
{
if (IsEmpty())
{
Console.WriteLine("Tree is Empty !");
return;
}
if (ptr != null)
{
inorder(ptr.LChild);
Console.WriteLine(ptr.Data + " ");
inorder(ptr.RChild);
}
} //先序遍历
//根结点->遍历根结点的左子树->遍历根结点的右子树
public void preorder(TreeNode<T> ptr)
{
if (IsEmpty())
{
Console.WriteLine("Tree is Empty !");
return;
}
if (ptr != null)
{
Console.WriteLine(ptr.Data + " ");
preorder(ptr.LChild);
preorder(ptr.RChild);
}
} //后序遍历
//遍历根结点的左子树->遍历根结点的右子树->根结点
public void postorder(TreeNode<T> ptr)
{
if (IsEmpty())
{
Console.WriteLine("Tree is Empty !");
return;
}
if (ptr != null)
{
postorder(ptr.LChild);
postorder(ptr.RChild);
Console.WriteLine(ptr.Data + "");
}
} //层次遍历
//引入队列
public void LevelOrder(TreeNode<T> root)
{
if (root == null)
{
return;
}
CSeqQueue<TreeNode<T>> sq = new CSeqQueue<TreeNode<T>>();
sq.EnQueue(root);
while (!sq.IsEmpty())
{
//结点出队
TreeNode<T> tmp = sq.DeQueue();
//处理当前结点
Console.WriteLine("{0}", tmp);
//将当前结点的左孩子结点入队
if (tmp.LChild != null)
{
sq.EnQueue(tmp.LChild);
}
if (tmp.RChild != null)
{
sq.EnQueue(tmp.RChild);
}
}
}
}
二叉搜索树:结点的左子节点的值永远小于该结点的值,而右子结点的值永远大于该结点的值 称为二叉搜索树
 /// <summary>
/// 二叉搜索树:结点的左子节点的值永远小于该结点的值,而右子结点的值永远大于该结点的值 称为二叉搜索树
/// </summary>
public class LinkBinarySearchTree : LinkBinaryTree<indexnode>
{
//定义增加结点的方法
public void insert(indexnode element)
{
TreeNode<indexnode> tmp, parent = null, currentNode = null;
//调用FIND方法
find(element, ref parent, ref currentNode);
if (currentNode != null)
{
Console.WriteLine("Duplicates words not allowed");
return;
}
else
{
//创建结点
tmp = new TreeNode<indexnode>(element);
if (parent == null)
Head = tmp;
else
{
if (element.Key < parent.Data.Key)
parent.LChild = tmp;
else
parent.RChild = tmp;
}
}
} //定义父结点
public void find(indexnode element, ref TreeNode<indexnode> parent, ref TreeNode<indexnode> currentNode)
{
currentNode = Head;
parent = null;
while ((currentNode != null) && (currentNode.Data.Key.ToString() != element.Key.ToString()) && (currentNode.Data.Offset .ToString() != element.Offset .ToString()))//
{
parent = currentNode;
if (element.Key < currentNode.Data.Key)
currentNode = currentNode.LChild;
else
currentNode = currentNode.RChild;
}
} //定位结点
public void find(int key)
{
TreeNode<indexnode> currentNode = Head;
while ((currentNode != null) && (currentNode.Data.Key.ToString () != key.ToString ()))
{
Console.WriteLine(currentNode.Data.Offset.ToString());
if (key < currentNode.Data.Key)
currentNode = currentNode.LChild;
else
currentNode = currentNode.RChild;
}
} //中序遍历
//遍历根结点的左子树->根结点->遍历根结点的右子树
public void inorderS(TreeNode<indexnode> ptr)
{
if (IsEmpty())
{
Console.WriteLine("Tree is Empty !");
return;
}
if (ptr != null)
{
inorderS(ptr.LChild);
Console.WriteLine(ptr.Data.Key + " ");
inorderS(ptr.RChild);
}
} //先序遍历
//根结点->遍历根结点的左子树->遍历根结点的右子树
public void preorderS(TreeNode<indexnode> ptr)
{
if (IsEmpty())
{
Console.WriteLine("Tree is Empty !");
return;
}
if (ptr != null)
{
Console.WriteLine(ptr.Data.Key + " ");
preorderS(ptr.LChild);
preorderS(ptr.RChild);
}
} //后序遍历
//遍历根结点的左子树->遍历根结点的右子树->根结点
public void postorderS(TreeNode<indexnode> ptr)
{
if (IsEmpty())
{
Console.WriteLine("Tree is Empty !");
return;
}
if (ptr != null)
{
postorderS(ptr.LChild);
postorderS(ptr.RChild);
Console.WriteLine(ptr.Data.Key + "");
}
}
} /// <summary>
/// 循环顺序队列
/// </summary>
/// <typeparam name="T"></typeparam>
class CSeqQueue<T>
{
private int maxsize; //循环顺序队列的容量
private T[] data; //数组,用于存储循环顺序队列中的数据元素
private int front; //指示最近一个已经离开队列的元素所占有的位置 循环顺序队列的对头
private int rear; //指示最近一个进入队列的元素的位置 循环顺序队列的队尾 public T this[int index]
{
get { return data[index]; }
set { data[index] = value; }
} //容量属性
public int Maxsize
{
get { return maxsize; }
set { maxsize = value; }
} //对头指示器属性
public int Front
{
get { return front; }
set { front = value; }
} //队尾指示器属性
public int Rear
{
get { return rear; }
set { rear = value; }
} public CSeqQueue()
{ } public CSeqQueue(int size)
{
data = new T[size];
maxsize = size;
front = rear = -;
} //判断循环顺序队列是否为满
public bool IsFull()
{
if ((front == - && rear == maxsize - ) || (rear + ) % maxsize == front)
return true;
else
return false;
} //清空循环顺序列表
public void Clear()
{
front = rear = -;
} //判断循环顺序队列是否为空
public bool IsEmpty()
{
if (front == rear)
return true;
else
return false;
} //入队操作
public void EnQueue(T elem)
{
if (IsFull())
{
Console.WriteLine("Queue is Full !");
return;
}
rear = (rear + ) % maxsize;
data[rear] = elem;
} //出队操作
public T DeQueue()
{
if (IsEmpty())
{
Console.WriteLine("Queue is Empty !");
return default(T);
}
front = (front + ) % maxsize;
return data[front];
} //获取对头数据元素
public T GetFront()
{
if (IsEmpty())
{
Console.WriteLine("Queue is Empty !");
return default(T);
}
return data[(front + ) % maxsize];//front从-1开始
} //求循环顺序队列的长度
public int GetLength()
{
return (rear - front + maxsize) % maxsize;
}
}

C#实现二叉树--二叉链表结构的更多相关文章

  1. C语言递归实现二叉树(二叉链表)的三种遍历和销毁操作(实验)

    今天写的是二叉树操作的实验,这个实验有三个部分: ①建立二叉树,采用二叉链表结构 ②先序.中序.后续遍历二叉树,输出节点值 ③销毁二叉树 二叉树的节点结构定义 typedef struct BiTNo ...

  2. 二叉树的二叉链表存储结构及C++实现

    前言:存储二叉树的关键是如何表示结点之间的逻辑关系,也就是双亲和孩子之间的关系.在具体应用中,可能要求从任一结点能直接访问到它的孩子. 一.二叉链表 二叉树一般多采用二叉链表(binary linke ...

  3. c使用二叉链表创建二叉树遇到的一些疑问和思考

    二叉链表存储二叉树 学习的时候参考的是<大话数据结构>,书中是这样定义的 typedef char TElemType; typedef struct BiTNode { TElemTyp ...

  4. 树(二叉树 & 二叉搜索树 & 哈夫曼树 & 字典树)

    树:n(n>=0)个节点的有限集.有且只有一个root,子树的个数没有限制但互不相交.结点拥有的子树个数就是该结点的度(Degree).度为0的是叶结点,除根结点和叶结点,其他的是内部结点.结点 ...

  5. 树&二叉树&二叉搜索树

    树&二叉树 树是由节点和边构成,储存元素的集合.节点分根节点.父节点和子节点的概念. 二叉树binary tree,则加了"二叉"(binary),意思是在树中作区分.每个 ...

  6. 建立二叉树的二叉链表存储结构(严6.70)--------西工大noj

    #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct TreeNode ...

  7. 二叉树(二叉链表实现)JAVA代码

      publicclassTest{       publicstaticvoid main(String[] args){           char[] ch =newchar[]{'A','B ...

  8. 建立二叉树的二叉链表(严6.65)--------西工大noj

    需要注意的点:在创建二叉树的函数中,如果len1==len2==0,一定要把(*T)置为NULL然后退出循环 #include <stdio.h> #include <stdlib. ...

  9. Trees on the level (二叉链表树)

    紫书:P150 uva122 Background Trees are fundamental in many branches of computer science. Current state- ...

随机推荐

  1. 一个成功的Git分支模型

    原文: http://www.juvenxu.com/2010/11/28/a-successful-git-branching-model/ 本文中我会展示一种开发模型,一年前该模型就已经被我用在所 ...

  2. LM && NTLM && ophcrack && RainBow table (转)

    Windows密码的加密方式:Windows 主要使用以下两种(包含但不限于)算法对用户名和密码进行加密:分 别是LanManager(LM)和NTLM,LM只能存储小于等于14个字符的密码hash, ...

  3. 使用VirtualBox在Ubuntu下虚拟Windows XP共享文件夹设置方法

    1.首先保证虚拟的Windows XP有虚拟光驱(正常安装的都是有的,因为在ubuntu下一般都是用硬盘虚拟安装的),然后在已经运行起来的Windows XP菜单栏上选择“设备-安装增强功能“,如果不 ...

  4. 编写SHELL脚本--编写简单脚本

    1.简单脚本文件hello.sh,内容如下 #!/bin/bash pwd ls -al 执行脚本:bash hello.sh  或者使用root命令:  ./hello.sh 2.接受用户参数 $0 ...

  5. 微信支付(APP支付)-服务端开发(一)

    微信支付,首先需要注册一个商户平台公众账号,(网址:https://pay.weixin.qq.com/index.php/home/d_login) 目前微信支付的接入方式有四种方式:公众号支付,A ...

  6. 如果你喜欢python,那你迟早会喜欢上julia的!

    你可曾想过有那么一门语言: 这门语言能够有C语言一样的速度,Ruby一样得活力(dynamism).像homoiconic一样的语言,它像Lisp一样有宏,但是也像Matlab一样有显而易见.熟悉的数 ...

  7. Java对象的内存实际占用

    一.打包和使用方法参考我之前的这篇文章,本文主要是更新了测量的类及方法,实际测试这个方法更准确. https://www.cnblogs.com/yoyotl/p/8421287.html 二.新的测 ...

  8. Latex学习(一)

    要在整个系统中使用TEX Live的字体(假定你有足够的权限),请依照下面的步骤来做: 1.将texlive-fontconfig.conf文件复制到/etc/fonts/conf.d/09-texl ...

  9. 第三部分:Android 应用程序接口指南---第四节:动画和图形---第一章 属性动画及动画与图形概述

    第1章 属性动画及动画与图形概述 Android提供了一系列强大的API来把动画加到UI元素中,以及绘制自定义的2D和3D图像中去.下面的几节将综述这些可用的API以及系统的功能,同时帮你做出最优的选 ...

  10. Atitit 项目文档规范化与必备文档与推荐文档列表

    Atitit 项目文档规范化与必备文档与推荐文档列表 ===========比较重要的必备文档========== 项目组名单通讯录( 包括项目组,客户沟通人等 需求文档 原型ui文档 开发计划表 项 ...