Documente Academic
Documente Profesional
Documente Cultură
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