二、二叉树
1.定义:二叉树是n(n>=0)个节点组成的有限集合。n=0时称为空二叉树;n>0的二叉树由一个根节点和两棵互不相
交的、分别称为左子树和右子树的二叉树构成。
2.二叉树的形式定义:二叉树(Binary Tree)简记为 BT,是一个二元组,
BT = (D, R)
其中:D是结点的有限集合;
R是结点之间关系的有限集合。
3.由二叉树的定义可知,二叉树与树的主要区别在于:二叉树的每个节点有其左、右之分,而且二叉树的节点最多只有两棵子树,所以二叉树的高度最多为2。
4.二叉树的性质:
1)、若根节点的层次为1,则二叉树第i层的节点数目最多为2的(i-1)次方(i>=1)。
2)、在深度为k的二叉树中,至多有2的k次方-1个节点。
3)、二叉树中,若叶子节点的数为n0,2度节点数位n2,则有n0=n2+1.
5.二叉树的基本操作:创建一棵二叉树、撤销二叉树、遍历二叉树、查找、插入节点、删除子树。
6.二叉树的遍历:先根次序、中根次序、后根次序。
微软提供了很多种树的结构,DOM是树结构的一个例子,其中有很多类用来操作访问DOM:
XmlNode
用于创建对象,这个对象可以保持 XML 文档的一个结点
XmlDocument
用于保持一个完整的 XML 文档对象。允许文档导航和编辑
XmlDocumentFragment
用于保持一个 XML 片段。可以将这个 XML 片段插入到文档中,或用作其它方面
XmlElement
用于在 XML 文档中操作元素类型的结点集合
XmlNodeList
代表 XML 文档中一个有序的结点集合
XmlNamedNodeMap
用于通过索引或索引值访问一个结点集合
XmlAttribute
用于在 XML 文档中操作属性类型结点
XmlCDataSection
用于操作 CDATA 部分
XmlText
用于保持一个元素或属性的文本内容
XmlComment
用于操作注释
XmlDocumentType
用于保持与文档类型声明相关的信息
XmlEntity
用于保持一个实体
XmlEntityReference
用于保持一个实体引用
XmlNotation
用于保持在一个文档类型声明(DTD)中声明的注释
XmlProcessingInstruction
用于保持一个处理指令
我自己想了解下二叉树的写法,然后正好书上有很多练习题,就动手写了BinaryTree类。因为中根遍历的非递归要用到栈、层次遍历的非递归算法要用到队列,所以改了一下自己的myStack类和myQueue类。
TreeNode.cs
Code
using System;
public class TreeNode
{
public char data;
public TreeNode left;
public TreeNode right;
public TreeNode(char ch)
{
data=ch;
left=null;
right=null;
}
public void preorderChild(TreeNode p)
{
if(p!=null)
{
Console.Write(p.data+" ");
preorderChild(p.left);
preorderChild(p.right);
}
}
public void inorderChild(TreeNode p)
{
if(p!=null)
{
inorderChild(p.left);
Console.Write(p.data+" ");
inorderChild(p.right);
}
}
public void postorderChild(TreeNode p)
{
if(p!=null)
{
postorderChild(p.left);
postorderChild(p.right);
Console.Write(p.data+" ");
}
}
}
BinaryTree.cs
Code
using System;
using System.Collections.Generic;
public class BinaryTree
{
public TreeNode root;
private static int i=0;
private static int j=0;
private static int len=0;
public BinaryTree(string str)
{
root=null;
if(str!=null)
{
root=create(str);
}
}
public BinaryTree()
{
root=null;
}
//表明空子树的先根遍历建立二叉树
public TreeNode create(string str)
{
TreeNode p=null;
if(str[i]!='.')
{
//Console.Write(str[i]+" ");
p=new TreeNode(str[i]);
i++;
p.left=create(str);
p.right=create(str);
}
else
i++;
if(p==null)
Console.WriteLine("返回null");
else
Console.WriteLine(p.data+" ");
return p;
}
//先根和中根遍历建立二叉树
public TreeNode increate(string prestr,string instr)
{
TreeNode p=null;
int n=prestr.Length;
if(n>0)
{
Console.WriteLine(prestr+" "+instr);
char ch = prestr[0];
int k=instr.IndexOf(ch);
Console.WriteLine("\t root="+ch+"\t k="+k);
if(k>=0)
{
p=new TreeNode(ch);
string presub = prestr.Substring(1,k);
string insub = instr.Substring(0,k);
//Console.Write(presub+" "+insub);
p.left = increate(presub,insub);
presub=prestr.Substring(k+1,n-k-1);
insub = instr.Substring(k+1,n-k-1);
p.right=increate(presub,insub);
}
}
return p;
}
//中根遍历二叉树的非递归算法
public void inorderT(BinaryTree t1)
{
myStack<TreeNode> s1=new myStack<TreeNode>(20);
TreeNode p = t1.root;
while(p!=null || !s1.IsEmpty())
{
if(p!=null)
{
s1.Push(p);
p=p.left;
}
else
{
p=s1.Pop();
Console.Write(p.data+" ");
p=p.right;
}
}
}
//二叉树的层次遍历算法
public void level(BinaryTree t1)
{
myQueue<TreeNode> q1=new myQueue<TreeNode>(20);
TreeNode p=t1.root;
q1.EnQueue(p);
while(!q1.IsEmpty())
{
p=q1.DeQueue();
Console.Write(p.data+" ");
if(p.left!=null)
q1.EnQueue(p.left);
if(p.right!=null)
q1.EnQueue(p.right);
}
}
public TreeNode createComplete(string str,int i)
{
TreeNode p=null;
len=str.Length;
if(i-1<len)
{
p=new TreeNode(str[i-1]);
p.left=createComplete(str,2*i);
p.right=createComplete(str,2*i+1);
}
return p;
}
public TreeNode listCreate(string str)
{
TreeNode p=null;
//Console.WriteLine(j+" ");
if(str[j]!='!')
{
if(str[j]>='A' && str[j] <='Z')
{
p=new TreeNode(str[j]);
j++;
//Console.WriteLine(p.data);
if(str[j]=='(')
{
j++;
p.left=listCreate(str);
j++;
p.right=listCreate(str);
j++;
}
}
if(str[j]=='#')
j++;
}
return p;
}
public void destroy(TreeNode p)
{
}
public void preorder()
{
root.preorderChild(root);
}
public void inorder()
{
root.inorderChild(root);
}
public void postorder()
{
root.postorderChild(root);
}
public static void Main()
{
string s1="ABD.GCE..FH#";
string s2 = "A(B(D(#,G),#),C(E,F(H,#)))!";
string s3 = "ABCDEFGH";
BinaryTree bt=new BinaryTree(s1);
Console.WriteLine("验证二叉树性质");
bt.preorder();
Console.WriteLine();
bt.inorder();
Console.WriteLine();
bt.postorder();
Console.WriteLine();
Console.WriteLine("层次遍历二叉树");
BinaryTree t = new BinaryTree();
t.root = t.createComplete(s3,1);
t.preorder();
Console.WriteLine();
t.inorder();
Console.WriteLine();
t.postorder();
Console.WriteLine();
BinaryTree t1 = new BinaryTree() ;
t1.root = t1.listCreate(s2);
Console.WriteLine("广义表建立二叉树");
t1.preorder();
Console.WriteLine();
t1.inorder();
Console.WriteLine();
t1.postorder();
Console.WriteLine();
Console.WriteLine("先根中根遍历确定二叉树");
BinaryTree t2 = new BinaryTree();
string prestr="ABDGCEFH";
string instr= "DGBAECHF";
t2.root = t2.increate(prestr,instr);
t2.preorder();
Console.WriteLine();
t2.inorder();
Console.WriteLine();
t2.postorder();
Console.WriteLine();
Console.WriteLine("中根的非递归遍历算法");
bt.inorderT(bt);
Console.WriteLine();
Console.WriteLine("层次非递归遍历算法");
bt.level(bt);
}
}
因为所有的算法都在这个类里面,所以比较乱。下次再复习的时候,我就将他们分离出来。
myStack.cs
Code
using System;
public class myStack<T>
{
int maxsize;
T[] data;
int top;
public T this[int index]
{
get{return data[index];}
set{data[index]=value;}
}
public int Maxsize{get;set;}
public int Top{get;set;}
public myStack(int size)
{
data = new T[size];
maxsize = size;
top=-1;
}
public int Length()
{
return top+1;
}
public void Clear()
{
top=-1;
}
public bool IsEmpty()
{
if(top==-1)
{
return true;
}
else
{
return false;
}
}
public bool IsFull()
{
if(top==maxsize-1)
{
return true;
}
else
{
return false;
}
}
public void Push(T e)
{
if(IsFull())
{
Console.WriteLine("栈已满!");
return ;
}
data[++top]=e;
}
public T Pop()
{
T temp=default(T);
if(IsEmpty())
{
Console.WriteLine("栈为空!");
return temp;
}
temp = data[top];
top--;
return temp;
}
public T GetTop()
{
if(IsEmpty())
{
Console.WriteLine("栈为空!");
return default(T);
}
return data[top];
}
}
myQueue.cs
Code
using System;
public class myQueue<T>
{
private T[] data;
private int maxsize;
private int front;
private int rear;
public myQueue(int size)
{
data=new T[size];
maxsize=size;
front=rear=0;
}
public T this[int index]
{
get{return data[index];}
set{data[index]=value;}
}
public int MaxSize{get;set;}
public int Front{get;set;}
public int Rear{get;set;}
public void Clear()
{
front=rear=-1;
}
public bool IsEmpty()
{
return front==rear;
}
public bool IsFull()
{
return front==rear%maxsize+1;
}
public bool EnQueue(T e)
{
if(!IsFull())
{
data[rear]=e;
rear=(rear+1)%maxsize;
return true;
}
else
{
Console.Write("队列已满");
return false;
}
}
public T DeQueue()
{
T temp=default(T);
if(!IsEmpty())
{
temp=data[front];
front=(front+1)%maxsize;
}
return temp;
}
public T GetFront()
{
if(IsEmpty())
{
Console.Write("队列为空");
return default(T);
}
return data[front];
}
public int Length()
{
return (rear-front+maxsize)%maxsize;
}
}
虽然看完了,但是还有很多是不了解的东西,有待下次复习时熟悉。