java括号生成二叉树,为淘汰赛创建二叉树

I am trying to create a binary tree for use in a knockout tournament. The tree consists of TNodes with Left and Right pointers.

This is the code that I have come up with (below); however, it runs into difficulties with the pointers in the CreateTree section.

Once this creates an empty tree of large enough size, I need to add the names on the Memo1.List to the bottoms of the tree so I can pair them up for matches.

How would I do this?

Type

TNodePtr = ^TNode;

TNode = Record

Data:String;

Left:TNodePtr;

Right:TNodePtr;

end;

Type

TTree = Class

Private

Root:TNodePtr;

Public

Function GetRoot:TNodePtr;

Constructor Create;

end;

var

MyTree:TTree;

function TTree.GetRoot: TNodePtr;

begin

Result:=Root;

end;

Constructor TTree.Create;

Var NewNode:TNodePtr;

Begin

New(NewNode);

NewNode^.Data:='Spam';

NewNode^.Left:=Nil;

NewNode^.Right:=Nil;

End;

Function Power(Base:integer;Exponent:integer):Integer; //Used for only positive powers in this program so does not need to handle negatives.

begin

If Base = 0 then

Power := 0

else If Exponent = 0 then

Power := 1

else //If Exponent > 0 then

Power:=Base*Power(Base, Exponent-1);

end;

Function DenToBinStr(Value:Integer):String;

Var iBinaryBit:integer;

sBinaryString:String;

Begin

While Value <> 0 do

begin

iBinaryBit:=Value mod 2;

sBinaryString:=sBinaryString+IntToStr(iBinaryBit);

Value:=Value div 2;

end;

Result:=sBinaryString;

end;

Procedure TForm1.CreateTree;

Var iRounds, iCurrentRound, iTreeLocation, iNodeCount, iMoreString, iAddedStringLength, iStringTree:Integer;

sBinary:String;

NewNode, ThisNode:TNodePtr;

begin

iRounds:=0;

While Power(2,iRounds) < Memo1.Lines.Count do {Calculates numbers of rounds by using whole powers of 2}

iRounds:=iRounds+1;

If iRounds > 0 then {Make sure there IS a round}

begin

For iCurrentRound:=1 to iRounds do {Select the round we are currently adding nodes to}

begin

iTreeLocation:=Power(2,iCurrentRound); {Works out the number of nodes on a line}

For iNodeCount:= 0 to iTreeLocation do {Selects the node we are currently working on}

begin

ThisNode:=MyTree.GetRoot;

sBinary:=DenToBinStr(iNodeCount); {Gets the tree traversal to that node from the root}

If Length(sBinary) < iCurrentRound then {Makes sure that the tree traversal is long enough, Fills spare spaces with Left because 0 decimal = 0 binary (we need 00 for 2nd round)}

begin

iMoreString:= iCurrentRound-Length(sBinary);

for iAddedStringLength := 0 to iMoreString do

sBinary:='0'+sBinary;

end;

iStringTree:=0; {Init iStringTree, iStringTree is the position along the binary string (alt the position down the tree)}

While iStringTree <= iCurrentRound-1 do {While we are not at the location to add nodes to, move our variable node down the tree}

begin

If sBinary[iStringTree]='0' then

ThisNode:=ThisNode^.Left

else If sBinary[iStringTree]='1' then

ThisNode:=ThisNode^.Right;

iStringTree:=iStringTree+1;

end;

New(NewNode); {Create a new node once we are in position}

NewNode^.Data:='Spam';

NewNode^.Left:=Nil;

NewNode^.Right:=Nil;

If sBinary[iCurrentRound]='0' then

ThisNode^.Left:=NewNode

else If sBinary[iCurrentRound]='1' then

ThisNode^.Right:=NewNode;

ThisNode.Data:='Spam';

Showmessage(ThisNode.Data);

end;

end;

end;

{1.2Add on byes}

{1.2.1Calculate No Of Byes and turn into count. Change each count into binary

equivalent then flip the bits}

//iByes:= Memo1.Lines.Count - Power(2,iRounds);

{1.2.2Add node where 0 is left and 1 is right}

{2THEN FILL TREE using If node.left and node.right does not exist then write

next name from list[q] q++}

{3THEN DISPLAY TREE}

end;

解决方案

Think about building the tree differently altogether by building it from the leaves. If you have a queue of nodes, you can take two nodes off the front, join them together with a new node, and add that new node to the end of the queue. Repeat until you run out of nodes, and you'll have a tournament bracket with the same number of rounds you'd get from trying to build the tree from the root.

Here's code that builds the tree and fills the leaves with names from the memo.

var

Nodes: TQueue;

Node: PNode;

s: string;

begin

Nodes := TQueue.Create;

try

// Build initial queue of leaf nodes

for s in Memo1.Lines do begin

New(Node);

Node.Data := s;

Node.Left := nil;

Node.Right := nil;

Nodes.Push(Node);

end;

// Link all the nodes

while Nodes.Count > 1 do begin

New(Node);

Node.Left := Nodes.Pop;

Node.Right := Nodes.Pop;

Nodes.Push(Node);

end;

Assert((Nodes.Count = 1) or (Memo1.Lines.Count = 0));

if Nodes.Empty then

Tree := TTree.Create

else

Tree := TTree.Create(Nodes.Pop);

finally

Nodes.Free;

end;

end;

What's nice about that code is that at no point do we know or care what level any particular node needs to be at.

If the number of competitors is not a power of two, then some of the competitors at the end of the list may get a "bye" round, and they'll be scheduled to play the winners at the top of the list. The code above has a minimal number of nodes. Your code may have a number of "spam" nodes that don't represent any actual match in the tournament.

The tree object should own the nodes it contains, so it should have a destructor, like this:

destructor TTree.Destroy;

procedure FreeSubnodes(Node: PNode);

begin

if Assigned(Node.Left) then

FreeSubnodes(Node.Left);

if Assigned(Node.Right) then

FreeSubnodes(Node.Right);

Dispose(Node);

end;

begin

FreeSubnodes(Root);

inherited;

end;

You'll notice I changed how the tree's constructor is called, too. If the tree is empty, it doesn't need to have any nodes. If the tree isn't empty, then we'll supply it with its nodes when we create it.

constructor TTree.Create(ARoot: PNode = nil);

begin

inherited;

Root := ARoot;

end;

If you have occasion to copy a tree, then you'll need to copy all its nodes, too. If you don't, then when you free one tree, the copy's root-node pointer will suddenly become invalid.

constructor TTree.Copy(Other: TTree);

function CopyNode(Node: PNode): PNode;

begin

if Assigned(Node) then begin

New(Result);

Result.Data := Node.Data;

Result.Left := CopyNode(Node.Left);

Result.Right := CopyNode(Node.Right);

end else

Result := nil;

end;

begin

inherited;

Root := CopyNode(Other.Root);

end;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值