Sunteți pe pagina 1din 9

4/28/2016

BinaryTree

BinaryTree
1.Abstractideaofatree:
Atreeisanotherdatastructurethatyoucanusetostoreinformation.Unlikestacksandqueues,
whicharelineardatastructures,treesarehierarchicaldatastructures.
Sayingthatthestructureofatreeishierarchicalmeansthatthingsareorderedaboveorbelow
otherthings.Forexample,thearmyishierarchical,withgeneralsabovecolonels,andcolonels
abovelieutenants,etc.
Hereisanexampleofatreeholdingletters:
tree

j<root
/\
fk
/\\
ahz<leaves

TreeVocabulary
Let'snowintroducesomevocabularywithoursampletree...Theelementatthetopofthetreeis
calledtheroot.Theelementsthataredirectlyunderanelementarecalleditschildren.The
elementdirectlyabovesomethingiscalleditsparent.Forexample,aisachildoffandfisthe
parentofa.Finally,elementswithnochildrenarecalledleaves.
Iskaleaf?Whoisitsparent?
Howmanyparentscanelementshave?
Aside:Ifyouweretodrawthepictureaboveupsidedown,itwouldlooklikearealtree,with
theleavesatthetopandtherootatthebottom...However,weusuallydrawtreedatastructures
aswe'vedoneabove.
Uses
Therearemanyreasonstouseatreetostoreinformation.Onereasonmightbebecauseyou
wanttostoreinformationthatnaturallyformsahierarchy.Forexample,thefilesystemona
computer:
filesystem

/<root
/\
...home
/\
ugradcourse
//|\
...cs101cs112cs113

Despitethehierarchicalorderofthestructureofthetree,theorderenforcedonobjectsinthe
http://www.cs.bu.edu/teaching/c/tree/binary/

1/9

4/28/2016

BinaryTree

treewilldependonhowweusethetree.Thisjustmeansthatunlikeastackwhoseoperations
areusuallylimitedtopushandpop,therearemanydifferentkindsoftreesandwaystouse
them.Thus,thisflexibilitymakesthemmoreakintolinkedlists.
Anotherreasontouseatreeisbecausetreesmakesomeoperationsmoreefficient(we'lldiscuss
thatatsomelatertime).
RecursiveDataStructure
Atreecanbeviewedasarecursivedatastructure.Why?Rememberthatrecursivemeansthat
somethingisdefinedintermsofitself.Here,thismeansthattreesaremadeupofsubtrees.
Forexample,let'slookatourtreeoflettersandexaminethepartstartingatfandeverything
underit...
tree

j
/\
fk
/\\
ahz

Doesn'titlooklikeatreeitself?Inthissubtree,whatisf(recallourvocabulary)?
Whataboutjustz?Doesn'titlooklikeasubtree?
BinaryTrees
Wecantalkabouttreeswherethenumberofchildrenthatanyelementhasislimited.Inthetree
above,noelementhasmorethan2children.Fortherestofthisexample,wewillenforcethisto
bethecase.
Atreewhoseelementshaveatmost2childreniscalledabinarytree.
Sinceeachelementinabinarytreecanhaveonly2children,wetypicallynamethemtheleft
andrightchild.
2.Treeoperations:
Asmentioned,therearedifferentkindsoftrees(e.g.,binarysearchtrees,23trees,AVLtrees,
tries,justtonameafew).
Whatoperationswewillneedforatree,andhowtheywork,dependsonwhatkindoftreewe
use.However,therearesomecommonoperationswecanmention:
Add:

Placesanelementinthetree(whereelementsendupdependsonthekindoftree).
Forexample,Add(tree,i)mightgive:
tree

j<root
/\
fk
http://www.cs.bu.edu/teaching/c/tree/binary/

2/9

4/28/2016

BinaryTree

/\\
ahz
\
i<newleaf
Remove:

Removessomethingfromthetree(howthetreeisreorganizedafteraremovaldependson
thekindoftree).
Forexample,Remove(tree,h)mightgive:
tree

j<root
/\
fk
/\\
aiz

Here,imoveduptotakeitsplace.
IsMember:

Reportswhethersomeelementisinthetree.
Forexample,IsMember(tree,a)shouldgiveatruevalueandIsMember(tree,y)should
giveafalsevalue.
Otheroperationsmaybenecessary,dependingonthekindoftreeweuse.
3.TreerepresentationinC:
SincewewanttobeabletorepresentatreeinC,howarewegoingtostorethishierarchical
structure?
Canweuseanarray?
Answer:Certainly!Therearetimeswhenwecanuseanarraytorepresentatree.
However,wecanalsodosomethingalongthelinesofalinkedlist.Forexample,justaslinked
listnodesholdoneelementandpointtothenextnode...
|
v

|a|+>|b|+>|c|0|

wecouldhavetreenodesthatholdoneelementandpointtotheirchildren...

|j|
||
|||
/\
vv

So,ourfirstexampletreeofletterswouldlooksomethinglike:
http://www.cs.bu.edu/teaching/c/tree/binary/

3/9

4/28/2016

BinaryTree

|
v

|j|
||
|||
/\
vv

|f||k|
||||
||||0||
/\\
vvv

|a||h||z|
||||||
|0|0||0|0||0|0|

Notethatsomenodesdon'thavealeftand/orrightchild,sothosepointersareNULL.
Also,justasweneedapointertothefirstnodetokeeptrackofalinkedlisthere,weneeda
pointertotherootnodetokeeptrackofatree.
Specialcase:EmptyTree
Whataboutwhenthetreeisempty.Howdowerepresentanemptytree?
Answer:Therearenonodes,sothepointertotherootshouldbeNULL.
4.Datatypesforatree:
Beforeweimplementtreefunctions,wemustdecidehowtouseCtypestoimplementthe
aboverepresentationforatree.AnadditionalconstraintisthatwewanttousetheADT/CDT
methodofhidingdetailsofadatastructure.We'llstickwithoursimpleexample,atreeof
characters.
Asusual,we'llwantourtreedatastructureinitsownmodule.
Now,peoplewilluseourtreesomethinglikethefollowing:
#include"tree.h"
...
treeADTt1,t2;
charch;
...
/*Setuptrees.*/
t1=TreeCreate();
t2=TreeCreate();
TreeAdd(t1,'a');
TreeAdd(t2,ch);
...
/*Cleanuptrees.*/
http://www.cs.bu.edu/teaching/c/tree/binary/

4/9

4/28/2016

BinaryTree

TreeDestroy(t1);
TreeDestroy(t2);

Thatmeans,weneedtodefine:
theADT(abstracttypethatpeopleusingthetreeneed).
theCDT(thepartoftheimplementationthatkeepstrackofthetree).
theelementtype(tomakeiteasytochangethetypeofthingsheldinthetree).
thenodetype(rememberweareusingnodestoholdtheelements).
Theorganizationofthesetypesinthetreemodulefilesareasfollows:
tree.h

tree.c

#include"tree.h"

typeofelement

typeofnode

abstracttypeoftree

concretetypeoftree

Note:We'llgetthetypesfromtree.hintree.csincewealwaysincludetheheaderfora
moduleintheimplementation(.c)partofthemodule.
Again,theinterface(.h)forthetreewillneedtohaveaabstracttypeforthetree(forpeopleto
definetreevariables)andthetypeofanelement(forfunctionalprototypes)...
Theimplementation(.c)ishiddenfromtheuserofatreeandwillholdthetypesweneedto
implementtheinternalsofthetree.Inotherwords,wewillstoreelementsinnodesandthe
informationneededtokeeptrackofatreemadeupofnodeswillbeheldintheconcretetype.
(Rememberthatweisolatethesetypesfromusersofthetree,i.e.,theydonotneedtoknowhow
thetreeisimplemented.Furthermore,isolatingthesetypeswillpreventthemfrombeingableto
messupthetree.)
Nowwecanfillinthesetypes.Let'sstartbottomupfromthesimplesttypeandworkourway
upthroughtypesthatusethesimplertypes.
Thetypeofanelementhasalreadybeendetermined:
typedefchartreeElementT;

Next,elementsofthetreearebeingstoredinnodes.Forourbinarytree,nodesmustcontainan
elementandpointersto2possiblechildren,theleftoneandtherightone.
Howdowedefinethetypeforanodewiththese3parts?
Answer:Wecancombinethemintoonetypewithastruct:
typedefstructtreeNodeTag{
treeElementTelement;
structtreeNodeTag*left,*right;
}treeNodeT;

Next,weneedsomethingthatholdsalltheinformationneededtokeeptrackofthetree.Since
thenodesalreadyholdanyelements,theonlythingthatismissingisthepointertotheroot
node.
http://www.cs.bu.edu/teaching/c/tree/binary/

5/9

4/28/2016

BinaryTree

Sincethispointerhastodowiththeimplementationofthetree,itbecomespartoftheconcrete
typeoftree,structtreeCDT:
typedefstructtreeCDT{
treeNodeT*root;
}treeCDT;

Finally,wemustfillinwhattheabstracttypeoftreeis(whichisalwaysapointertotheCDT):
typedefstructtreeCDT*treeADT;

So,wehavethefollowing:
tree.htree.c

#include"tree.h"
typedefchartreeElementT;typedefstructtreeNodeTag{

treeElementTelement;

structtreeNodeTag*left,

*right;

}treeNodeT;
typedefstructtreeCDT

*treeADT;

typedefstructtreeCDT{
treeNodeT*root;
}treeCDT;

5.Treefunctions:
Nowthatwehavethetypesfinished,let'simplementoneofthetreeoperations.Thetree
functionswe'llneedare:
Forgeneraltreeoperations:
TreeAdd()
TreeRemove()
TreeIsMember()
BecauseweareprogramminginC(setup/cleanup):
TreeCreate()
TreeDestroy()
Theonewe'llimplementisTreeIsMember().Inthismembershipfunction,we'llassumethatthe
elementsinatreeareinnoparticularorder,i.e.,thisfunctionwillbeforageneralbinarytree.
(Certainkindsoftreeshaveanordertotheirelementsmakingthisfunctioneasier.)
Testingmembershipexample
Supposewewanttoseeifhisinthetree...
tree

j<root
/\
fk
/\\
ahz<leaves

Thethingtodoisstartattheroot...
http://www.cs.bu.edu/teaching/c/tree/binary/

6/9

4/28/2016

BinaryTree

1.Theelementattheroot,j,isnotthethingwewant,sowe'llhavetolookattheleftand
rightsubtrees.We'llstartontheleft.
2.Theelementattherootoftheleftsubtree,f,isnotthethingwewant,sowehavetocheck
itssubtrees.We'llstartontheleftagain.
3.Theleftsubtree'srootisa(notwhatwewant).Sincewe'veexhaustedthatsubtree,we
shouldgobackuptofandtryitsrightsubtree.
4.Finally,therootoftherightsubtreeoffish,theelementwewerelookingfor,sowecan
reportthatwefoundit.
Youcanseehowthesearchwouldcontinuethroughthetreeifwedidn'tfindtheelementyet.
Basedonourexample,theabilitytobacktrack(e.g.,fromabacktof)iscritical.
Let'ssummarizewhatwedidaboveinanalgorithm.
Sinceatreecanbeviewedasarecursivedatastructure,wecanprobablycreateanalgorithm
thatisrecursive.Recursionwillalsogiveustheabilitytobacktrack,whichweneed.
Whatitmeansforthealgorithmtoberecursiveisthatitwilluseitself.
IsMember(tree,value)[recursive]

1.Ifthetreeisempty,returnfalse.
2.Checktoseeiftheelementattherootistheonewewant...
Ifso,returntrue.
Ifnot..
1.ChecktheleftsubtreewithIsMember(leftsubtree,value).
Iffound,returntrue.
2.ChecktherightsubtreewithIsMember(rightsubtree,value).
Iffound,returntrue.
3.returnfalse.
Note:Whenwereturnfalse,itdoesn'tnecessarilymeantheelementisnotinthewholetree,just
thesubtreeweareworkingon.
Youcanseethatthebasecasesarewhenweexhaustasubtreeorwhenwefindtheelement.
Weusetherecursiontochecksubtrees(whicharetreesthemselves).
6.TreeIsMember()function:
ToperformIsMemberrecursively,wewillstartwiththetopleveltreeandrecurseonsubtrees.
Thismeansthatweneedasingletypetorefertoboththetopleveltreeandallsubtrees,i.e.,a
typethatispresentthroughoutthetreedatastructure.
anADT
|
+>|root|aCDT
|||
+
|
v

|j|
||
|||
http://www.cs.bu.edu/teaching/c/tree/binary/

7/9

4/28/2016

BinaryTree

/\
vv

|f||k|
||||
||||0||
/\\
vvv

|a||h||z|
||||||
|0|0||0|0||0|0|

WecannotusetheADT(orCDT)torefertosubtreesbecausethereisonlyoneADT(andits
CDT),anditreferstothetopleveltree(seefigureabove).Theonlytypethatisappropriateis
nodepointer(treeNodeT*)therearenodepointersthatpointtothetopleveltree(therootpart
oftheCDT)andallsubtrees(alltheleftandrightpointers).
However,theuserofthetreedoesn'tknowaboutnodepointers,onlyADTs.So,TreeIsMember()
willbeawrapperfunctionthattakesatreeviaanADTandpassesthenodepointerattheroot
alongtoarecursivefunction.
WrapperIsMember
RememberthatIsMembershouldreturnatrue/falsevalue.So,ourwrapperfunctionwilllook
likethefollowing:
/*
*Reportwhethervalueisfoundinthetree.
*Assumethetreeisageneralbinarytree
*(i.e.,elementsareinnospecialorder).
*/
intTreeIsMember(treeADTtree,
treeElementTvalue)
{
returnRecIsMember(tree>root,value);
}

ItjustcallstherecursivefunctionRecIsMember()todothechecking.
7.RecursiveIsMemberfunction:
So,RecIsMember()getsaccesstothetree(andsubsequentsubtrees)vianodepointers...
staticintRecIsMember(treeNodeT*root,
treeElementTvalue);

Sinceitisahelperfunctionthatisnotaccessibleviatheinterface,wemakeitstaticand
prototypeitintheimplementationfile.
Now,allithastodoisthefollowing:
staticintRecIsMember(treeNodeT*root,
treeElementTvalue)
{
/*Makesuresubtreenotempty.*/
if(root==NULL)
return0;/*Notfound*/
http://www.cs.bu.edu/teaching/c/tree/binary/

8/9

4/28/2016

BinaryTree

/*
*Checkthevalueattherootof
*thecurrentsubtree.
*/
if(root>element==value)
return1;/*Found!*/
/*Checkleftsubtree.*/
if(RecIsMember(root>left,value))
return1;/*Foundinleftsubtree.*/
/*Checkrightsubtree.*/
returnRecIsMember(root>right,value);
}

BUCASCSBinaryTree
Copyright19932000byRobertI.Pitts<ripatbudotedu>.AllRightsReserved.

http://www.cs.bu.edu/teaching/c/tree/binary/

9/9

S-ar putea să vă placă și