数据结构与算法(C#实现)系列-----前言
Heavenkiller (
原创)
搞计算机的人都应该很清楚,语言只是一种工具,算法才是灵魂。现在的开发语言有很多,如C++,VB,Perl,java,c#,还有如脚本语言js,vbs等,在如此多的选择面前,很多人不知道该选择哪一种好。其实不管哪一种语言,既然他存在,就一定有他的价值,有它的特定用途,而这往往是其它语言所无法比拟的。譬如C++就适合于系统底层的编程,而java一般就用于对稳定性,兼容性要求较高的场合,正所谓各有所长。像我一般用C++编写网络基层和与操作系统相关的程序,用C#写ASP.NET等程序,必要的时候再辅以Rose, Rational XDE等建模工具。但无论选择哪一种语言,算法才是根本,掌握了算法,就掌握了所有语言的根本,以不变应万变。
微软的C#是一种全新的语言,利用它能快捷、高效地布署程序。现在关于C#的资料也已经有很多了,各个方面的资料都能找得到,但用C#做数据结构的似乎还没有什么,在CSDN上我只找到了三四篇,而且仅仅是讲了一下链表之类简单的数据结构。于是我利用空闲的时间用C#写了一些数据结构与算法的实现,希望对大家学习数据结构能够有所帮助。另外,由于时间仓促,难免出现一些纰漏,希望大家不吝赐教给予指正,我的email是[email protected].欢迎大家和我一起交流学习。
本系列包括树,N叉树,广义树,二叉树,BST二叉查找树,AVL平衡树,堆,二叉堆,以及图。还有一些如哈希表,散列,左翼树,二项树,Haffman编码树等因时间关系,暂时未能奉上,以后有时间再补上吧。
首先给大家展示一幅用Rational XDE for .NET 生成的类模型图,让大家对所有的类有一个大概的了解。
数据结构与算法(C#实现)系列---演示篇(一)
Heavenkiller(
原创)
这一篇主要是针对以后各篇的数据类型进行一个实质性的演示。因此希望大家具体看了各种数据结构的分析之后再看这篇。
主要包括如下几个方面的演示:
1.
堆栈。 演示了一个利用堆栈作的RPN计算器
2.
排序表。演示了一个利用排序表做的多项式表达式的加法运算
3.
广义树。演示了深度遍历和广度遍历
4. N
叉树。演示了N叉树的生成插入删除等基本操作
5.
表达式树。演示了一个用二叉树和堆栈做的可以将一个后缀表达式翻译为日常中熟悉的中缀表达式的例子
6. AVL
树。演示了基本操作
using System;
using System.Collections;
namespace DataStructure
{
///
/// Class1
的摘要说明。
///
class Show
{
///
///
应用程序的主入口点。
///
[STAThread]
static void Main(string[] args)
{
//
// TODO:
在此处添加代码以启动应用程序
//
while(true)
{
Console.WriteLine("please choose a the No. of a item you want to perform:");
Console.WriteLine("1.Stack----- RPNCalCulator");
Console.WriteLine("2.SortedList-----the addition of polynomial realized by sortedlist ");
Console.WriteLine("3.GeneralTree----depthtravesal and breathtraval");
Console.WriteLine("4.NaryTree");
Console.WriteLine("5.ExpressionTree");
Console.WriteLine("6.AVLTree");
Console.WriteLine("7.BinaryHeap");
Console.WriteLine("exit--Exit this programme");
//Test();
switch(Console.ReadLine())
{
case "1"://Show Stack
ShowStack_RPNCalCulator();
break;
case "2"://SortedList
ShowSortedList_Polynomial();
break;
case "3":
ShowGeneralTree_travel();
break;
case "4":
ShowNaryTree();//
演示一个三叉树的Attach和Detach
break;
case "5":
ShowExpressionTree();
break;
case "6":
ShowAVLTree();
break;
case "7":
ShowBinaryHeap();
break;
case "exit":
return;
default:
break;
}
}
}
public static void ShowBinaryHeap()
{
//
构造一个二叉堆, 包含2,4,6,8,10,12
BinaryHeap bHeap=new BinaryHeap(10);
bHeap.Enqueue(12);
bHeap.Enqueue(10);
bHeap.Enqueue(8);
bHeap.Enqueue(6);
bHeap.Enqueue(4);
bHeap.Enqueue(2);
//
测试Dequeue();
while(bHeap.Count!=0)
{
Console.WriteLine(bHeap.DequeueMin().ToString());
}
}
public static void ShowAVLTree()
{
AVLTree testAVL=new AVLTree(5);
testAVL.Insert(1);
testAVL.Insert(3);
testAVL.Insert(7);
testAVL.Insert(8);
testAVL.Insert(9);
testAVL.Insert(10);
testAVL.Insert(11);
PrintVisitor vis=new PrintVisitor();
Tree.InOrder inVis=new DataStructure.Tree.InOrder(vis);
testAVL.DepthFirstTraversal(inVis);
}
public static void ShowExpressionTree()
{
ExpressionTree.PostfixToInfix();
}
public static void ShowNaryTree()
{
//
构造一个三叉树,具体见图1-2
NaryTree A=new NaryTree(3,"A");
NaryTree B=new NaryTree(3,"B");
NaryTree C=new NaryTree(3,"C");
NaryTree D=new NaryTree(3,"D");
NaryTree E=new NaryTree(3,"E");
B.AttachSubtree(1,D);
B.AttachSubtree(2,E);
A.AttachSubtree(1,B);
A.AttachSubtree(3,C);
//---------------------------
Console.WriteLine("
广度遍历");
PrintVisitor vis=new PrintVisitor();
A.BreadthFirstTraversal(vis);//
广度遍历
Console.WriteLine("
前序遍历");
Tree.PreOrder preVisit=new DataStructure.Tree.PreOrder(vis);
A.DepthFirstTraversal(preVisit);
Console.WriteLine("
后序遍历");
Tree.PostOrder postVisit=new DataStructure.Tree.PostOrder(vis);
A.DepthFirstTraversal(postVisit);
Console.WriteLine("
中序遍历");
Tree.InOrder inVisit=new DataStructure.Tree.InOrder(vis);
A.DepthFirstTraversal(inVisit);
}
数据结构与算法(C#
实现)
系列---
演示篇(
二)
Heavenkiller(原创)
public static void ShowGeneralTree_travel()
{
IEnumerator tmpIEnum;
Tree.TraversalType travelType=0;
//---------------------提示----------------------------
Console.WriteLine("please choose a the No. of a item you want to travel:");
Console.WriteLine("1.BreadthFirst----- 广度遍历");
Console.WriteLine("2.PreDepthFirst-----前序遍历");
Console.WriteLine("3.InDepthFirst----中序遍历");
Console.WriteLine("4.PostDepthFirst----后序遍历");
switch(Console.ReadLine())
{
case "1"://Show Stack
travelType=Tree.TraversalType.Breadth;
Console.WriteLine("广度遍历");
break;
case "2"://SortedList
travelType=Tree.TraversalType.PreDepth;
Console.WriteLine("前序遍历");
break;
case "3":
travelType=Tree.TraversalType.InDepth;
Console.WriteLine("中序遍历");
break;
case "4":
travelType=Tree.TraversalType.PostDepth;
Console.WriteLine("后序遍历");
break;
default:
break;
}
//构造一棵广义树 generaltree
GeneralTree A=new GeneralTree("A");
GeneralTree B=new GeneralTree("B");
GeneralTree C=new GeneralTree("C");
GeneralTree D=new GeneralTree("D");
GeneralTree E=new GeneralTree("E");
GeneralTree F=new GeneralTree("F");
A.AttackSubtree(B);
A.AttackSubtree(C);
B.AttackSubtree(D);
B.AttackSubtree(E);
A.AttackSubtree(F);
//show the operation
Console.WriteLine("A.AttackSubtree(B)");
Console.WriteLine("A.AttackSubtree(C)");
Console.WriteLine("B.AttackSubtree(D)");
Console.WriteLine("B.AttackSubtree(E)");
Console.WriteLine("A.AttackSubtree(F)");
//--------------------------------------------------------
A.SetTraversalType(travelType);//设置遍历类型
tmpIEnum=A.GetEnumerator();
//Console.WriteLine("begin to depthfist travel:");
while(tmpIEnum.MoveNext())
{
Console.WriteLine(tmpIEnum.Current.ToString());
}
}
public static void ShowStack_RPNCalCulator()
{
//read a expression string and push every character into the stack in queue.
Console.WriteLine("this is performance for stack,you can input a string like this '123*+',then this subprogramme can compute it and get the result '7',this is RPN calculator. ");
Console.WriteLine("please input a expression string:");
string strExpression=Console.ReadLine();
char [] tmpChars=strExpression.ToCharArray(0,strExpression.Length);
Stack stackRPN=new Stack();
int numA,numB;
foreach(char tmp in tmpChars)
{
switch (tmp)
{
case '*':
numA=(int)stackRPN.Pop();
numB=(int)stackRPN.Pop();
stackRPN.Push(numA*numB);
break;
case '+':
numA=(int)stackRPN.Pop();
numB=(int)stackRPN.Pop();
stackRPN.Push(numA+numB);
break;
default:
stackRPN.Push(Int32.Parse(tmp.ToString()));
break;
}
}
Console.WriteLine("the result is:{0}",stackRPN.Pop().ToString());
}
数据结构与算法(C#
实现)
系列---
演示篇(
三)
Heavenkiller(原创)
public static void ShowSortedList_Polynomial()
{
//100+10*x+x^2 + 1+10*x+100x^2
SortedList tmpListA=new SortedList();
SortedList tmpListB=new SortedList();
SortedList tmpListC=new SortedList();//used to store the result
SortedList tmpKeyList=new SortedList();//used to store all keys of two polynomials
//init polynomial A and show it
tmpListA.Add(0,100);
tmpListA.Add(1,10);
tmpListA.Add(2,1);
ShowSortedList_ShowPolynomial("tmpListA",tmpListA.GetEnumerator());
//init polynomial B and show it
tmpListB.Add(0,1);
tmpListB.Add(1,10);
tmpListB.Add(2,100);
ShowSortedList_ShowPolynomial("tmpListB",tmpListB.GetEnumerator());
//init the key list which contains all keys of A and B but everyone once
IDictionaryEnumerator tmpIDic=tmpListA.GetEnumerator();
while(tmpIDic.MoveNext()!=false)
{
if(!tmpKeyList.ContainsKey(tmpIDic.Key))
{
tmpKeyList.Add(tmpIDic.Key,null);
}
}
tmpIDic=tmpListB.GetEnumerator();
while(tmpIDic.MoveNext()!=false)
{
if(!tmpKeyList.ContainsKey(tmpIDic.Key))
{
tmpKeyList.Add(tmpIDic.Key,null);
}
}
//Add A and B and show the result
tmpIDic=tmpKeyList.GetEnumerator();
while(tmpIDic.MoveNext()!=false)
{
object objA=null,objB=null,objC=null;
objC=tmpIDic.Key;
if(tmpListA.ContainsKey(objC))
objA=tmpListA[objC];
if(tmpListA.ContainsKey(objC))
objB=tmpListB[objC];
//objC=objA+objB;
//tmpKeyList[objC]=(int)objA+(int)objC;
tmpListC.Add(objC,(int)objA+(int)objB);
}
ShowSortedList_ShowPolynomial("the addition result of A and B",tmpListC.GetEnumerator());
}
public static void ShowSortedList_ShowPolynomial(string tip,IDictionaryEnumerator iDic)
{
string strExpress=null;
iDic.Reset();
while(iDic.MoveNext()!=false)
{
strExpress+=iDic.Value.ToString()+"*X^"+iDic.Key.ToString()+"+";
}
Console.WriteLine(tip+":"+strExpress);
}
}
数据结构与算法(C#
实现)
系列---
树(
一)
Heavenkiller(原创)
首先我们给树下一个定义:
树是一个有限的、非空的结点集,
T={r} or T1 or T2 or…or Tn
它具有下列性质:
1.集合指定的结点r叫做树的根结点
2.其余的结点可以划分成n个子集,T1,T2,…Tn(n>=0),其中每一个子集都是一棵树。
树的其它定义如度,叶子,高等就请大家查阅别的资料吧,到处都有的。
树的主要性质一个就是遍历,分为深度遍历和广度遍历
在这里分别实现为DepthFirstTravesal()和WidthFirstTravesal()
其中深度遍历又分为前序遍历、中序遍历、和后序遍历
这是是采用适配器技术实现的。
using System;
using System.Collections;
namespace DataStructure
{
///
/// Tree 的摘要说明。
/// when traverse, traversaltype can't be changed,or throw a exception
/// 支持枚举、比较、深度复制
///
public abstract class Tree:IEnumerable,IComparable
{
public Tree()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
protected Queue keyqueue=new Queue();//仅仅用于枚举时存放数据,不参与Equals实现中的比较
protected TraversalType traversaltype=TraversalType.Breadth;// choose a traversal type,and DepthFirst is default
//protected uint degree=0;//degree of the tree, init it as 0
//protected uint height=0;//height of the tree, init it as 0
//枚举不同的遍历类型
public enum TraversalType
{
Breadth=1,//广度遍历
PreDepth=2,//前序遍历
InDepth=3,//中序遍历
PostDepth=4//后序遍历
};
//public virtual abstract object Key{}
public abstract Tree this[uint _index]{get;set;}//if I only use get, can I change it later?
public abstract object Key{get;}
public abstract uint Degree{get;}
//public abstract uint Height{get;}
public void SetTraversalType(TraversalType _type){traversaltype=_type;}//set a traversal a type, if it's not set manually, DepthFirst will be chosen in default
public abstract bool IsEmpty();// property takes the place of IsEmpty()
public abstract bool IsLeaf();
//Only Visit, needn't queue
public virtual void DepthFirstTraversal(IPrePostVisitor _vis)//middle depthfirst traversal
{
//通过_vis使用不同的访问者来进行前序、后序、中序遍历
if(!IsEmpty())
{
_vis.PreVisit(this.Key);
if( this.Degree>=1 )
{
if( this.Degree>=2)
{
for(uint i=0;i<(this.Degree-1);i++)//
{
this[i].DepthFirstTraversal(_vis);//recursive call
//_vis.Visit(this.Key);
}
}
this[this.Degree-1].DepthFirstTraversal(_vis);
}
_vis.PostVisit(this.Key);
}
}
public virtual void BreadthFirstTraversal(IVisitor _vis)//breadth first traversal
{
Queue tmpQueue=new Queue();//used to help BreadthFirstTraversal
//this.keyqueue=new Queue();//store keys
if(!this.IsEmpty())
tmpQueue.Enqueue(this);//enqueue the root node at first
while(tmpQueue.Count!=0)//until the number of the queue is zero
{
Tree headTree=(Tree)tmpQueue.Dequeue();
//this.keyqueue.Enqueue(headTree.Key);
_vis.Visit(headTree.Key);
for(uint i=0;i
{
Tree childTree=headTree[i];
if(!childTree.IsEmpty())
tmpQueue.Enqueue(childTree);
}
}
}
//------------------------------------------------end------------------------------------
//内部成员类 用于提供不同遍历类型的访问者
public class PreOrder:IPrePostVisitor
{
private IVisitor visitor;
public PreOrder(IVisitor _vis){visitor=_vis;}
#region IPrePostVisitor 成员
public void PreVisit(object _obj)
{
// TODO: 添加 PreOrder.PreVisit 实现
this.visitor.Visit(_obj);
}
public void Visit(object _obj)
{
// TODO: 添加 PreOrder.Visit 实现
}
public void PostVisit(object _obj)
{
// TODO: 添加 PreOrder.PostVisitor 实现
}
#endregion
}
数据结构与算法(C#
实现)
系列---
树(
二)
Heavenkiller(原创)
public class InOrder:IPrePostVisitor
{
private IVisitor visitor;
public InOrder(IVisitor _vis){visitor=_vis;}
#region IPrePostVisitor 成员
public void PreVisit(object _obj)
{
// TODO: 添加 InOrder.PreVisit 实现
}
public void Visit(object _obj)
{
// TODO: 添加 InOrder.Visit 实现
this.visitor.Visit(_obj);
}
public void PostVisit(object _obj)
{
// TODO: 添加 InOrder.PostVisitor 实现
}
#endregion
}
public class PostOrder:IPrePostVisitor
{
private IVisitor visitor;
public PostOrder(IVisitor _vis){visitor=_vis;}
#region IPrePostVisitor 成员
public void PreVisit(object _obj)
{
// TODO: 添加 PostOrder.PreVisit 实现
}
public void Visit(object _obj)
{
// TODO: 添加 PostOrder.Visit 实现
}
public void PostVisit(object _obj)
{
// TODO: 添加 PostOrder.PostVisitor 实现
this.visitor.Visit(_obj);
}
#endregion
}
protected class EnumVisitor:IVisitor
{
Queue thisQueue;
public EnumVisitor(Queue _que)
{
this.thisQueue=_que;
}
#region IVisitor 成员
public void Visit(object _obj)
{
// TODO: 添加 EnumVisitor.Visit 实现
this.thisQueue.Enqueue(_obj);
}
#endregion
}
#region IEnumerable 成员
public IEnumerator GetEnumerator()
{
// TODO: 添加 Tree.GetEnumerator 实现
EnumVisitor vis=new EnumVisitor(this.keyqueue);
switch (this.traversaltype)
{
case TraversalType.Breadth:
BreadthFirstTraversal(vis);
break;
case TraversalType.PreDepth:
PreOrder preVis=new PreOrder(vis);
DepthFirstTraversal(preVis);
break;
case TraversalType.InDepth:
InOrder inVis=new InOrder(vis);
DepthFirstTraversal(inVis);
break;
case TraversalType.PostDepth:
PostOrder postVis=new PostOrder(vis);
DepthFirstTraversal(postVis);
break;
default:
Console.WriteLine("WARNING:please set a travel type first!--void SetTraversalType(TraversalType _type) ");
//throw new Exception("WARNING:please set a travel type first!");//if not set a type, a exception will happen
break;
}
return this.keyqueue.GetEnumerator();
}
#endregion
数据结构与算法(C#
实现)
系列---
树(
三)
Heavenkiller(原创)
//overwrite Object.Equals() --- reference type realization
public override bool Equals(object _obj)
{
if( _obj==null )
return false;//因为this不可能为null
if( ! (this.GetType()==_obj.GetType()) )
return false;//类型不相等也不相等
Tree tmpObj=(Tree)_obj;
//比较引用成员
if( !Object.Equals(this.Key,tmpObj.Key) )
return false;
//比较值类型成员
if( !this.Degree.Equals(tmpObj.Degree) )
return false;
//if( !this.Height.Equals(tmpObj.Height) )
//return false;
return true;
}
//在此重载 ==,!= 后, 在以后继承的类中不必实现了
public static bool operator==(Tree _treeA,Tree _treeB)
{
return Object.Equals(_treeA,_treeB);
}
public static bool operator!=(Tree _treeA,Tree _treeB)
{
return !(_treeA==_treeB);
}
#region IComparable 成员
public virtual int CompareTo(object obj)
{
// TODO: 添加 Tree.CompareTo 实现
return 0;
}
#endregion
}
}
数据结构与算法(C#
实现)
系列---
广义树(
一)
Heavenkiller(原创)
广义树和基本树的主要区别就是有任意的度
using System;
using System.Collections;
namespace DataStructure
{
///
/// GeneralTree 的摘要说明。
/// general tree is a tree which has a arbitrary degree and no empty tree
/// use ArrayList to replace ListAsLinkedList
///
public class GeneralTree:Tree
{
protected object key=null;
protected uint degree=0;
//protected uint height=0;
protected ArrayList treeList=new ArrayList();
public GeneralTree(object _objKey)
{
//
// TODO: 在此处添加构造函数逻辑
//
key=_objKey;
degree=0;
//height=0;
ArrayList treeList=new ArrayList();
}
public virtual void AttackSubtree(GeneralTree _gTree)
{
this.treeList.Add(_gTree);
++degree;
}
public virtual GeneralTree DetachSubtree(GeneralTree _gTree)
{
this.treeList.Remove(_gTree);
degree--;
return _gTree;//????? how to remove ,reference or object????
}
public override Tree this[uint _index]
{
get
{
if(_index>=this.degree)
throw new Exception("my:out of index");
return (Tree)treeList[(int)_index];
}
set
{
treeList[(int)_index]=value;
}
}
数据结构与算法(C#
实现)
系列---
广义树(
二)
Heavenkiller(原创)
public override object Key{get{return this.key;}}
public override uint Degree{get{return this.degree;}}
//public override uint Height{get{return this.height;}}
public override bool IsEmpty()// property takes the place of IsEmpty()
{
return false;//generaltree won't be empty for ever
}
public override bool IsLeaf()
{
return this.degree==0;//if this tree's degree is zero, it means the tree has no subtrees, so it is leaf certainly
}
//overwrite Object.Equals() --- reference type realization
public override bool Equals(object _obj)
{
if( !base.Equals(_obj) )
return false;//基类比较不相等,则不相等
//基类中的一些条目在此可免去
//在基类中已判定其为GeneralTree类型,故转型不会失败
GeneralTree tmpTree=(GeneralTree)_obj;
//比较引用成员
if( !Object.Equals(this.treeList,tmpTree.treeList) )
return false;
//比较值类型成员
return true;
}
}
}
数据结构与算法(C#
实现)
系列---N
叉树(
一)
Heavenkiller(原创)
N叉树的每一节点度数都相同,为N
using System;
using System.Collections;
namespace DataStructure
{
///
/// NaryTree 的摘要说明。-----N叉树
///
public class NaryTree:Tree
{
// member variables
protected object key;
protected uint degree;
protected ArrayList treeList=new ArrayList();
//protected uint height=0;//暂时默认为0
//create an empty tree whose attribute of degree is _degree
public NaryTree(uint _degree)
{
//
// TODO: 在此处添加构造函数逻辑
//
this.key=null;
this.degree=_degree;
this.treeList=null;
}
//构造一棵叶子结点的N叉树
public NaryTree(uint _degree,object _key)
{
this.key=_key;
this.degree=_degree;
this.treeList=new ArrayList();
this.treeList.Capacity=(int)_degree;
for(int i=0;i
{
this.treeList.Add( this.GetEmptyInstance(_degree) );
}
}
//-----------------------------------------------------------------
protected virtual object GetEmptyInstance(uint _degree)
{ return new NaryTree(_degree); }
//-------------------------------------------------------------------
//judge whether the tree is an empty tree
public override bool IsEmpty()
{ return this.key==null; }
//判定是否是叶子结点。如果即不是空树且每一棵子树均为空树,则为叶子结点
public override bool IsLeaf()
{
if(IsEmpty())
return false;
for(uint i=0;i
{
if( !(this[i].IsEmpty()) )
return false;
}
return true;
}
//-----------------------------------Inherited Attributes---------------------------------
public override object Key
{
get
{
return this.key;
}
}
//索引器
public override Tree this[uint _index]
{
get
{
if( _index>=this.degree )
throw new Exception("My:out of index!");//如果出界,则抛出异常
if( this.IsEmpty() )
return null;//如果是空树,则索引器返回一个 null
return (Tree)this.treeList[(int)_index];
}
set
{
this.treeList[(int)_index]=value;
}
}
数据结构与算法(C#
实现)
系列---N
叉树(
二)
Heavenkiller(原创)
public override uint Degree
{
get
{
return this.degree;
}
}
//-------------------------------------------------------------------------------------
//只用于空树结点
public virtual void AttachKey(object _obj)
{
if(!IsEmpty())
throw new Exception("My:this node must be a empty tree node!");
this.key=_obj;
this.treeList=new ArrayList();//产生一个degree长的数组,并将其初始化为空树
this.treeList.Capacity=(int)this.degree;
for(int i=0;i
{
treeList.Add(new NaryTree(this.degree));
}
/*
foreach(object tmpObj in this.treeList)
{
tmpObj=new NaryTree(this.degree);
}
*/
}
//只用于叶子结点,将叶子结点变为一个空结点,并返回叶子结点关键字的引用
public virtual object DetachKey()
{
if(!IsLeaf())
throw new Exception("My:this node must be a leaf node!");
object result=this.key;//store this leaf node temporary
this.key=null;
this.treeList=null;
return result;
}
//将子树连接到指定树的第num个结点上,前提是这个结点必须是空结点,并且度数相同,否则抛出异常
public virtual void AttachSubtree(uint num,NaryTree _naryTree)
{
if(this.IsEmpty())
throw new Exception("My:it can't be a empty tree!");
if(!(this[num-1].IsEmpty()) | this.degree!=_naryTree.degree )
throw new Exception("My:this[i-1] must be empty and they should have the same degree!");
this[num-1]=_naryTree;
}
//仅为非空树定义,从给定树中删去它的第i棵子树并连上一个空树,度数相同,并且返回删除的子树引用
public virtual NaryTree DetachSubtree(uint num)
{
if (IsEmpty())
throw new Exception("My:it can't be empty! ");
NaryTree tmpTree=this;
((NaryTree)this[num-1]).key=null;
((NaryTree)this[num-1]).treeList=null;
return this;
}
//----------------------------------------------------------------------------------
}
}
数据结构与算法(C#
实现)
系列---AVLTree
(一)
using System;
using System.Collections;
namespace DataStructure
{
///
/// AVLTree 的摘要说明。-----平衡二叉查找树
///
public class AVLTree:BST
{
protected int height;//空树的高定义为-1;
//构造一棵空的二叉查找树
public AVLTree():base()
{
//
// TODO: 在此处添加构造函数逻辑
//
height=-1;
}
public AVLTree(object _obj):base(_obj)
{
height=0;
}
//------------------------------------------------------------------
protected override object GetEmptyInstance(uint _degree)
{ return new AVLTree(); }
//------------------------------------------------------------------
protected int BalanceFactor()
{
if (this.IsEmpty() )
return 0;
return ((AVLTree)this.Left).height-((AVLTree)this.Right).height;
}
//调整高度
protected void AdjustHeight(){ this.height=Math.Max( ((AVLTree)this.Left).height, ((AVLTree)this.Right).height)+1; }
//平衡时的四种旋转方式
protected void LLRotation()
{
if( this.IsEmpty() )
throw new Exception("My:invalid operation!");
AVLTree avlB=new AVLTree(this.key);
avlB.AttachSubtree(1,(AVLTree)this[0][1]);
avlB.AttachSubtree(2,(AVLTree)this[1]);
this.key=this[0].Key;
this[0]=this[0][0];
this[1]=avlB;
//调整两个节点的高度
((AVLTree)this.Right).AdjustHeight();
this.AdjustHeight();
}
protected void LRRotation()
{
if( this.IsEmpty() )
throw new Exception("My:invalid operation!");
((AVLTree)this.Left).RRRotation();
this.LLRotation();
}
protected void RRRotation()
{
if( this.IsEmpty() )
throw new Exception("My:invalid operation!");
AVLTree avlB=new AVLTree(this.key);
avlB.AttachSubtree(1,(AVLTree)this[0]);
avlB.AttachSubtree(2,(AVLTree)this[1][0]);
//avlA.AttachSubtree(1,avlB);
//this=avlA;
this.key=this[1].Key;
this[0]=avlB;
this[1]=this[1][1];
//调整两个节点的高度
((AVLTree)this.Left).AdjustHeight();
this.AdjustHeight();
}
protected void RLRotation()
{
if( this.IsEmpty() )
throw new Exception("My:invalid operation!");
((AVLTree)this.Right).LLRotation();
this.RRRotation();
}
数据结构与算法(C#
实现)
系列---AVLTree
(二)
//---------------override--------------------
public override void AttachKey(object _obj)
{
if(!IsEmpty())
throw new Exception("My:this node must be a empty tree node!");
this.key=_obj;
//产生一个degree长的数组,并将其初始化为空树
this.treeList=new ArrayList();
this.treeList.Capacity=(int)this.degree;
for(int i=0;i
{
treeList.Add(new AVLTree());
}
//
this.height=0;
}
//在改动树的结构后平衡树
public override void Balance()
{
this.AdjustHeight();
//大于1则说明不平衡
if( Math.Abs(this.BalanceFactor())>1)
{
if(this.BalanceFactor()>0)
{
if (((AVLTree)this.Left).BalanceFactor()>0)
this.LLRotation();
else
this.LRRotation();
}
else
{
if (((AVLTree)this.Right).BalanceFactor()<0)
this.RRRotation();
else
this.RLRotation();
}
}
}
public int Height{get{return this.height;}}
}
数据结构与算法(C#
实现)
系列---
二叉树
using System;
using System.Collections;
namespace DataStructure
{
///
/// BinaryTree 的摘要说明。
///
public class BinaryTree:NaryTree
{
//构造二叉空树
public BinaryTree():base(2)
{
//
// TODO: 在此处添加构造函数逻辑
//
}
public BinaryTree(object _obj):base(2,_obj)
{}
//------------------------------------------------------------------
protected override object GetEmptyInstance(uint _degree)
{ return new BinaryTree(_degree); }
//------------------------------------------------------------------
//重写深度遍历
public override void DepthFirstTraversal(IPrePostVisitor _vis)
{
if ( !IsEmpty() )
{
_vis.PreVisit(this.Key);
this[0].DepthFirstTraversal(_vis);
_vis.Visit(this.Key);
this[1].DepthFirstTraversal(_vis);
_vis.PostVisit(this.Key);
}
}
//二叉树大小的比较
//先比较关键字,如果相等,再比较左子树,如果再相等,则比较右子树----如此递归
#region IComparable 成员
public override int CompareTo(object obj)
{
// TODO: 添加 BinaryTree.CompareTo 实现
//因为Comare()中已经进行了类型断定,故不会出现转型错误
BinaryTree tmpTree=(BinaryTree)obj;
if( this.IsEmpty() )
return tmpTree.IsEmpty()?0:-1;
if( tmpTree.IsEmpty() )
return 1;
int result=Comparer.Default.Compare(this,tmpTree);
if(result==0)
result=this[0].CompareTo(tmpTree[0]);
if(result==0)
result=this[1].CompareTo(tmpTree[1]);
return result;
}
#endregion
}
}
数据结构与算法(C#
实现)
系列---
二叉堆(数组实现)
using System;
using System.Collections;
namespace DataStructure
{
///
/// BinaryHeap 的摘要说明。-------二叉堆(基于数组的实现)
///
public class BinaryHeap:IPriorityQueue
{
protected ArrayList array;
//建立一个最多容纳_length个对象的空二叉堆
public BinaryHeap(uint _length)
{
//
// TODO: 在此处添加构造函数逻辑
//
array=new ArrayList((int)_length);
array.Capacity=(int)_length;
}
//堆中对象个数
public virtual int Count{get{return this.array.Count;}}
//将成员数组变成用1为基数表达的形式
public virtual object Item(int _i)
{
if(_i>=this.array.Capacity)
throw new Exception("My:out of index");//不能出界
return this.array[_i-1];
}
#region IPriorityQueue 成员
//先将空洞放在数组的下一个位置上,也就是i(注:基数是1),然后和[i/2]位置上的数比较,如果小于则将空洞上移到[i/2]位置,而原先[i/2]位置上的对象则移到[i]上,否则就将空洞变为_obj----如此递归
public void Enqueue(Object _obj)
{
// TODO: 添加 BinaryHeap.Enqueue 实现
if( this.array.Count==this.array.Capacity )
throw new Exception("My:priority queue is full");//如果优先队列已满,则抛出异常
this.array.Add(new object());
int i=this.array.Count;
while(i>1&&Comparer.Default.Compare(this.array[i/2-1],_obj )>0)
{
//this.Item(i)=this.Item(i/2);
this.array[i-1]=this.array[i/2-1];
i/=2;
}
this.array[i-1]=_obj;
}
public object FindMin()
{
// TODO: 添加 BinaryHeap.FindMin 实现
if( this.array.Count==0 )
throw new Exception("My:priority queue is empty");//如果队列是空的,则抛出异常
return this.array[0];
}
public object DequeueMin()
{
// TODO: 添加 BinaryHeap.DequeueMin 实现
object tmpObj=this.FindMin();
int i=1;
while( (2*i+1)<=this.array.Count)
{
if( Comparer.Default.Compare(this.array[2*i-1],this.array[2*i])<=0 )
{
this.array[i-1]=this.array[2*i-1];
this.array[2*i-1]=tmpObj;
i=2*i;
}
else
{
this.array[i-1]=this.array[2*i];
this.array[2*i]=tmpObj;
i=2*i+1;
}
}
object delObj=this.array[i-1];//暂时储存要删去的元素
if(i!=this.array.Count)//如果搜索到的对象就是数组的最后一个对象,则什么都不要做
{
this.array[i-1]=this.array[this.array.Count-1];//添补空洞
}
this.array.RemoveAt(this.array.Count-1);//将最后一个对象删除
return delObj;
}
#endregion
}
}
C#
算法(一)选择排序
嗨!朋友们,C#将是未来网络开发的首选语言。本人用了C#开发出选择排序算法。希望能为C#语言的学习者带来一些益处。
不要忘了,学语言要花大力气学数据结构和算法。
using System;
public class SelectionSorter
{
// public enum comp {COMP_LESS,COMP_EQUAL,COMP_GRTR};
private int min;
// private int m=0;
public void Sort(int [] list)
{
for(int i=0;i
{
min=i;
for(int j=i+1;j
{
if(list[j]
min=j;
}
int t=list[min];
list[min]=list[i];
list[i]=t;
// Console.WriteLine("{0}",list[i]);
}
}
}
public class MainClass
{
public static void Main()
{
int[] iArrary=new int[]{1,5,3,6,10,55,9,2,87,12,34,75,33,47};
SelectionSorter ss=new SelectionSorter();
ss.Sort(iArrary);
for(int m=0;m<=13;m++)
Console.WriteLine("{0}",iArrary[m]);
}
}
已经成功的编译。
C#
算法
(
二
)
插入排序
朋友们,我最近加紧写C#的一些算法。选择排序已经推出的。现推出插入算法。
对想提高C#语言编程能力的朋友,我们可以互相探讨一下。
如:下面的程序,并没有实现多态,来,帮它实现一下。
using System;
public class InsertionSorter
{
public void Sort(int [] list)
{
for(int i=1;i
{
int t=list[i];
int j=i;
while((j>0)&&(list[j-1]>t))
{
list[j]=list[j-1];
--j;
}
list[j]=t;
}
}
}
public class MainClass
{
public static void Main()
{
int[] iArrary=new int[]{1,5,3,6,10,55,9,2,87,12,34,75,33,47};
InsertionSorter ii=new InsertionSorter();
ii.Sort(iArrary);
for(int m=0;m<=13;m++)
Console.WriteLine("{0}",iArrary[m]);
}
}
已经编译运行通过.这太简单了,我不做详细介绍了.
C#
算法
(
三
)
希尔排序
朋友们,我最近加紧写C#的一些算法。选择排序,插入算法是我已经推出的。现推出希尔排序.今后,如有时间我将依次推出其它的算法编写。
希尔排序是将组分段,进行插入排序.
对想提高C#语言编程能力的朋友,我们可以互相探讨一下。
如:下面的程序,并没有实现多态,来,帮它实现一下。using System;
public class ShellSorter
{
public void Sort(int [] list)
{
int inc;
for(inc=1;inc<=list.Length/9;inc=3*inc+1);
for(;inc>0;inc/=3)
{
for(int i=inc+1;i<=list.Length;i+=inc)
{
int t=list[i-1];
int j=i;
while((j>inc)&&(list[j-inc-1]>t))
{
list[j-1]=list[j-inc-1];
j-=inc;
}
list[j-1]=t;
}
}
}
}
public class MainClass
{
public static void Main()
{
int[] iArrary=new int[]{1,5,3,6,10,55,9,2,87,12,34,75,33,47};
ShellSorter sh=new ShellSorter();
sh.Sort(iArrary);
for(int m=0;m<=13;m++)
Console.WriteLine("{0}",iArrary[m]);
}
}
已经编译通过.
C#
算法
(
四
)
快速排序
前面我已经推出了三种排序的算法,比较简单。今天我又写了快速排序的算法。希望多多指教。具体的思想,我不做答了。前人的经验。
using System;
namespace QuickSorter
{
public class QuickSorter
{
private void Swap(ref int l,ref int r)
{
int s;
s=l;
l=r;
r=s;
}
public void Sort(int [] list,int low,int high)
{
int pivot;
int l,r;
int mid;
if(high<=low)
return;
else if(high==low+1)
{
if(list[low]>list[high])
Swap(ref list[low],ref list[high]);
return;
}
mid=(low+high)>>1;
pivot=list[mid];
Swap(ref list[low],ref list[mid]);
l=low+1;
r=high;
do
{
l++;
while(list[r]>=pivot)
r--;
if(l
Swap(ref list[l],ref list[r]);
}while(l
list[low]=list[r];
list[r]=pivot;
if(low+1
Sort(list,low,r-1);
if(r+1
Sort(list,r+1,high);
}
}
public class MainClass
{
public static void Main()
{
int[] iArrary=new int[]{1,5,3,6,10,55,9,2,87,12,34,75,33,47};
QuickSorter q=new QuickSorter();
q.Sort(iArrary,0,13);
for(int m=0;m<=13;m++)
Console.WriteLine("{0}",iArrary[m]);
}
}
}
已经编译通过,运行环境:windows xp VC#.net 7.0
C#
排序算法大全
冒泡排序
本人用了C#开发出冒泡排序算法。希望能为C#语言的学习者带来一些益处。不要忘了,学语言要花大力气学数据结构和算法。
using System;
namespace BubbleSorter
{
public class BubbleSorter
{
public void Sort(int [] list)
{
int i,j,temp;
bool done=false;
j=1;
while((j<list.Length)&&(!done))
{
done=true;
for(i=0;i<list.Length-j;i++)
{
if(list[i]>list[i+1])
{
done=false;
temp=list[i];
list[i]=list[i+1];
list[i+1]=temp;
}
}
j++;
}
}
}
public class MainClass
{
public static void Main()
{
int[] iArrary=new int[]{1,5,13,6,10,55,99,2,87,12,34,75,33,47};
BubbleSorter sh=new BubbleSorter();
sh.Sort(iArrary);
for(int m=0;m<iArrary.Length;m++)
Console.Write("{0} ",iArrary[m]);
Console.WriteLine();
}
}
}
选择排序
本人用了C#开发出选择排序算法。希望能为C#语言的学习者带来一些益处。不要忘了,学语言要花大力气学数据结构和算法。
using System;
namespace SelectionSorter
{
public class SelectionSorter
{
private int min;
public void Sort(int [] list)
{
for(int i=0;i<list.Length-1;i++)
{
min=i;
for(int j=i+1;j<list.Length;j++)
{
if(list[j]<list[min])
min=j;
}
int t=list[min];
list[min]=list[i];
list[i]=t;
}
}
}
public class MainClass
{
public static void Main()
{
int[] iArrary=new int[]{1,5,3,6,10,55,9,2,87,12,34,75,33,47};
SelectionSorter ss=new SelectionSorter();
ss.Sort(iArrary);
for(int m=0;m<iArrary.Length;m++)
Console.Write("{0} ",iArrary[m]);
Console.WriteLine();
}
}
}
插入排序
插入排序算法。对想提高C#语言编程能力的朋友,我们可以互相探讨一下。如:下面的程序,并没有实现多态,来,帮它实现一下。
using System;
namespace InsertionSorter
{
public class InsertionSorter
{
public void Sort(int [] list)
{
for(int i=1;i<list.Length;i++)
{
int t=list[i];
int j=i;
while((j>0)&&(list[j-1]>t))
{
list[j]=list[j-1];
--j;
}
list[j]=t;
}
}
}
public class MainClass
{
public static void Main()
{
int[] iArrary=new int[]{1,13,3,6,10,55,98,2,87,12,34,75,33,47};
InsertionSorter ii=new InsertionSorter();
ii.Sort(iArrary);
for(int m=0;m<iArrary.Length;m++)
Console.Write("{0}",iArrary[m]);
Console.WriteLine();
}
}
}
希尔排序
希尔排序是将组分段,进行插入排序. 对想提高C#语言编程能力的朋友,我们可以互相探讨一下。如:下面的程序,并没有实现多态,来,帮它实现一下。
using System;
namespace ShellSorter
{
public class ShellSorter
{
public void Sort(int [] list)
{
int inc;
for(inc=1;inc<=list.Length/9;inc=3*inc+1);
for(;inc>0;inc/=3)
{
for(int i=inc+1;i<=list.Length;i+=inc)
{
int t=list[i-1];
int j=i;
while((j>inc)&&(list[j-inc-1]>t))
{
list[j-1]=list[j-inc-1];
j-=inc;
}
list[j-1]=t;
}
}
}
}
public class MainClass
{
public static void Main()
{
int[] iArrary=new int[]{1,5,13,6,10,55,99,2,87,12,34,75,33,47};
ShellSorter sh=new ShellSorter();
sh.Sort(iArrary);
for(int m=0;m<iArrary.Length;m++)
Console.Write("{0} ",iArrary[m]);
Console.WriteLine();
}
}
}
*C#
冒泡算法
参加多次笔试,居然有几次都考到了冒泡算法,一次是C#版的填空,一次是javascript版的全部写出。
虽然每次都凭着我对冒泡法的理解给弄出来的,但是多多少少与标准模式有点差别,在网上搜了一下关于C#版的冒泡算法,居然也没有一个象样的,自己对照算法模式认真写了一个C#版的,已经测试成功。
同时附上【冒泡排序动画演示】
public void BubbleSort(int[] R)
{
int i,j,temp;
//交换标志
bool exchange;
//最多做R.Length-1趟排序
for(i=0; i
{
//本趟排序开始前,交换标志应为假
exchange=false;
for(j=R.Length-2; j>=i; j--)
{
//交换条件
if(R[j+1]
{
temp=R[j+1];
R[j+1]=R[j];
R[j]=temp;
//发生了交换,故将交换标志置为真
exchange=true;
}
}
//本趟排序未发生交换,提前终止算法
if(!exchange)
{
break;
}
}
}
*
八皇后问题的
C#
解答
改编自V星[视窗王子]应答程序,如下:
using System;
class Queen{
const int SIZE = 8;//皇后数
public static void Main()
{
int[] Queen = new int [SIZE];//每行皇后的位置
int y,x,i,j,d,t=0;
y = 0;
Queen[0] = -1;
while( true )
{
for (x=Queen[y]+1; x
{
for (i=0;i
{
j = Queen[i];
d = y-i;
//检查新皇后是否与以前的皇后能相互攻击
if ((j==x)||(j==x-d)||(j==x+d))
break;
}
if (i>=y)
break;//不攻击
}
if (x == SIZE) //没有合适的位置
{
if (0==y)
{
//回朔到了第一行
Console.WriteLine("Done");
break; //结束
}
//回朔
Queen[y]=-1;
y--;
}
else
{
Queen[y]=x;//确定皇后的位置
y++;//下一个皇后
if (y
Queen[y]=-1;
else
{
//所有的皇后都排完了,输出
Console.WriteLine("/n" + ++t +':');
for(i=0;i
{
for (j=0;j
if(Queen[i] == j)
Console.Write('Q');
else
Console.Write('.');
Console.WriteLine();
}
y = SIZE -1;//回朔
}
}
}
}
}
八皇后有解92个。
另:我认为foreach和for循环在意义上是不同的,在这里应该用for.
望指正,此致。
重粒子@Y2K0928
--------------------------------------------------------------------------------
送交者: 视窗王子 列出所有还未回答的带星问题 于 9月 28, 2000 09:16:
主题:多谢重粒子兄 答复本贴
阅读相关的帖子
--------------------------------------------------------------------------------
回答: 给视窗王子:八皇后问题C#版 由 重粒子 于 9月 27, 2000 22:32:
非常感谢您的注解以及优化,不过比较了一下结果,好像我俩的结果是一致的。:-)
另外,关于打印的那部分,如果这样优化:
Console.Write(Queen[i]==j ? 'Q':'.');
似乎可以更简洁一些,粒子兄以为呢?
关于foreach和for, 的确,无论从字面上还是在文档中都让人感到for似乎比foreach更有确定性。然而,foreach毕竟是也一种遍历,关键是遍历的可重复性和法则,即,每次遍历的结果是可预计的和相同的。另外,我们可以通过定制Enumerator来决定foreach的遍历行为,使得“无法遍历”或“不可预计的”变成“可遍历”且“可预计的”,如同C++中重载[]算符使得链表“变成”了数组。
对于一些基本数据结构的遍历,比如数组,foreach还是和for一致的,不过粒子兄提醒的好,对任何事千万不要想当然,它除了会把你引入歧途外不会给你带来任何好处。
目前我正在和MS的C# Developer打交道,事实上现在MS中有部分产品的部分代码用上了C# (不知是正式的还是做试验)。很希望和粒子兄以及各位大大小小的虾兄弟姐妹们一起玩玩这新鲜玩意儿。
*
对
C#
泛型中的
new()
约束的一点思考
对于new()约束,大家可能有一个误解,以为使用了new约束之后,在创建对象时与非泛型的版本是一致的:
public class Tester
where T:new()
{
public Tester()
{
t = new T();//等同于非泛型版本的new? 例如 object o = new object();?
}
private T t;
}
事实上,使用new关键字的作用只是让编译器在泛型实例化之处,检查所绑定的泛型参数是否具有无参构造函数:
Tester t = new Tester();
//此处编译器会检查SomeType是否具有无参构造函数。若没有则会有compile error。
而Tester类的构造函数中的new代码,实际上等同于下面的代码:
public class Tester
where T:new()
{
public Tester()
{
t = System.Activator.CreateInstance();
}
private T t;
}
也就是说,仍然是用反射机制来获取泛型对象的实例的。
*C# 2.0
新特性探究之模拟泛型和内置算法
在C#2.0中,匿名方法、IEnumerable接口和匿名方法的合作,使很多的编程任务变得非常的简单,而且写出来的程序非常的优美。 比如,我们可以写出如下的代码:
List<Book> thelib = Library.getbooks();
List<Book> found = thelib.FindAll(delegate(Book curbook)
{
if (curbook.isbn.StartsWith("..."))
return true;
return false;
});
foreach (Book b in found)
Console.WriteLine(b.isbn);
这段程序非常简单的展示给我们需要查找的信息,代码也非常的直接易懂。内置的数据结构给了我们强大的算法支持,不过,能不能够为自定义的类定义类似的算法呢?
比如,如果我有一个自定义的Library类并没有使用List<Book>存储数据,而是使用某种自定义的数据结构,我能不能也让用户使用类似的语法,忽略存储细节的使用匿名委托来实现特定的算法呢?
答案当然是肯定的,而且在C#中实现这样的功能是非常的简单。
首先让我们看看FindAll中用到的匿名委托的原型 public delegate bool Predicate<T>(T obj);
很明显的,上面的代码等于注册了一个搜索的回调,而在List内部定义了某种遍历的机制,从而实现了一个漂亮的算法结构Closure。
看到了这些,我们就可以定义自己的算法结构了,首先,我定义了一个如下的类
public class MyVec<T>
{
public static MyVec<T> operator +(MyVec<T> a, T b)
{
a._list.Add(b);
return a;
}
public override string ToString()
{
StringBuilder builder = new StringBuilder();
foreach (T a in _list)
{
builder.Append(a.ToString());
builder.Append(",");
}
string ret = builder.Remove(builder.Length - 1, 1).ToString();
return ret;
}
public MyVec<T<>findAll(Predicate<T> act)
{
MyVec<T:>t2 = new MyVec<T>();
foreach(T i in _list)
{
if (act(i))
t2._list.Add(i);
}
return t2;
}
// this is the inner object
private List<T> _list = new List<T>();
}
这个类中包含了一个的List<T>结构,主要是为了证实我们的想法是否可行,事实上,任何一个可以支持foreach遍历的结构都可以作为内置的数据存储对象,我们会在后面的例子中给出一个更加复杂的实现。
下面是用于测试这个实验类的代码:
static void Main(string[] args)
{
MyVec<int> a = new MyVec<int>();
a += 12;
a += 15;
a += 32;
MyVec<int> b = a.findAll(delegate(int x)
{
if (x < 20) return true; return false;
}
);
Console.WriteLine("vection original");
Console.WriteLine(a.ToString());
Console.WriteLine("vection found");
Console.WriteLine(b.ToString());
Console.ReadLine();
}
编译,执行,程序输出:
vection original
12,15,32
vection found
32
和我们预期的完全相同。很明显的,List内部的算法与我们预期的基本相同。
Predicate<T>仅仅是为了仿照系统的实现而采用的一个委托,事实上可以使用自己定义的任何委托作为回调的函数体。
通过使用IEnumberable接口,可以实现对任意结构的遍历,从而对任何数据结构定义强大的算法支持。