c++数据结构11.docx
《c++数据结构11.docx》由会员分享,可在线阅读,更多相关《c++数据结构11.docx(34页珍藏版)》请在冰豆网上搜索。
![c++数据结构11.docx](https://file1.bdocx.com/fileroot1/2022-11/25/92a30907-0ffd-4c23-b5a5-4e8333711ff9/92a30907-0ffd-4c23-b5a5-4e8333711ff91.gif)
c++数据结构11
第五章:
树
1.若用二叉链表作为二叉树的存储表示,试针对以下问题编写递归算法:
(1)统计二叉树中叶结点的个数。
intBinaryTree:
:
leaf(BinTreeNode*ptr)
{
if(ptr==NULL)return0;
elseif(ptr->leftChind==NULL&&ptr->rightChild==NULL)return1;
elsereturnleaf(ptr->leftChild)+leaf(prt->rightChild);
}
(2)以二叉树为参数,交换每个结点的做子女和有子女。
voidBinaryTree:
:
exchange(BinTreeNode*ptr)
{
BinTreeNode*temp;
if(ptr->leftChild!
=NULL||prt->rightChild!
=NULL)
{
temp=ptr->leftChild;
ptr->leftChild=ptr->rightChild;
ptr->rightChild=temp;
exchage(ptr->leftChild);
exchage(ptr->rightChild);
}
}
2.可以用缩格(或移行)的文本形式(IndentedText)来表示一棵树的结点数据。
例如下面图1所示的树的缩格文本形式如图2所示。
试设计一个算法,将用左子女-右兄弟链表表示的树用缩格文本形式输出。
图1
A
BC
D
E
F
G
H
I
J
K
图2
templateclassTree;
templateclassTreeNode{//树的结点类
friendclassTree;
private:
Typedata;//数据
TreeNode*firstChild,*nextSibling;//子女及兄弟指针
public:
TreeNode(Typevalue=0,TreeNode*fc=NULL,TreeNode*ns=NULL)
:
data(value),firstChild(fc),nextSibling(ns){}//构造函数
TypegetData(){returndata;}//取得结点数据
TreeNode*getFirstChild(){returnfirstChild;}//取得第一个子女地址
TreeNode*getNextSibling(){returnnextSibling;}//取得下一个兄弟地址
voidsetData(Typex){data=x;}//修改结点数据
voidsetFirstChild(TreeNode*fc){firstChild=fc;}//修改第一个子女地址
voidsetNextSibling(TreeNode*ns){nextSibling=ns;}//修改下一个兄弟地址
};
templateclassTree{//树类
private:
TreeNode*root,*current;//根指针及当前指针
voidPreOrder(ostream&out,TreeNode*p);
intFind(TreeNode*p,Typetarget);
voidRemovesubTree(TreeNode*p);
intFindParent(TreeNode*t,TreeNode*p);
public:
Tree(){root=current=NULL;}//构造函数,建立空树
voidBuildRoot(TyperootVal);
intRoot();//寻找根,使之成为当前结点
intFirstChild();//寻找当前结点的第一个子女
intNextSibling();//寻找当前结点的下一个兄弟
intParent();//寻找当前结点的双亲结点
//树的其他公共操作
……
}
2.2
将以左子女-右兄弟链表表示的树用缩格文本形式打印出来的算法如下:
#include
#include“Tree.h”
templatevoidindentedText(TreeNode*t,intk){
if(t!
=NULL){
for(inti=0;icout<getData();
t=t->getFirstChild();
while(t!
=NULL){
indentedText(t,k+1);
t=t->getNextSibling();
}
}
3.ChunShu
Description
Thegenealogyofafamilycanberepresentedasarootedtree,inwhicheachnodecorrespondstoamemberofthefamily,andeachedgeconnectsamembertohis/herparent.Therootisthefounderofthefamilyandhasnoparentinthegenealogy;leafnodescorrespondtothosewithnochild.ThedistancebetweentwomembersinagenealogyiscalledaChunShuinKorea,whichisdefinedasthenumberofedgesonthepathbetweenthem.Forexample,inthegenealogyshownbelow,theChunShubetweenpersons1and3is3whiletheChunShubetweenpersons1and5is5.Fromnowon,theChunShubetweenpersoniandpersonjwillbedenotedbyChunShu(i,j).
Arootedtreeinwhicheachnode,unlessitisaleafnode,hasexactlytwochildrenisa2-tree.Inotherwords,a2-treeisabinarytreeinwhicheachnodehaseithertwochildrenornone.Forexample,thetreeshownaboveisa2-tree.
Considerafamilywhosecompletegenealogyisunknown.Whatisknownaboutthegenealogyofthefamilyisthatitisa2-treeandithasnleafnodes.Assumethattheleafnodesarenumberedfrom1,2,...,nintheleft-to-rightorderasshowninthefigureabove.AlsoknownaboutthegenealogyistheChunShubetweeneverypairofleafnodeswhosenumbersareconsecutive;i.e.,ChunShu(i,i+1)foreveryi(1<=i<=n-1)isknown.
Itiswellknownthatonlyfromtheinformationaboutthefamilygivenabove,theChunShubetweenanytwoleafnodescanbecomputed.
YouaretowriteaprogramtocomputetheChunShubetweentwoleafmembersx,y(1<=xFortheexampleabove,youaregivenasinput,n=6,ChunShu(1,2)=3,ChunShu(2,3)=2,ChunShu(3,4)=5,ChunShu(4,5)=3,andChunShu(5,6)=2.Fromthisinformation,youcancomputeChunShu(1,6),thatis,theChunShubetweenx=1andy=6.
Input
TheinputconsistsofTtestcases.Thenumberoftestcases(T)isgivenonthefirstlineoftheinputfile.Thefirstlineofeachtestcasecontainsanintegern(3<=n<=1000),thenumberofleafnodes.Thenextlinecontainsasequenceofn?
1integerswhichareChunShu(1,2),ChunShu(2,3),...,ChunShu(n-1,n).Thelastlineofeachtestcasecontainstwodistinctintegersx,y(1<=xOutput
Printexactlyonelineforeachtestcase.ThelineistocontainanintegerthatistheChunShubetweentwoleafnodes.Thefollowingshowssampleinputandoutputfortwotestcases.
SampleInput
2
6
32532
16
6
42425
26
SampleOutput
5
5
#include
#include
usingnamespacestd;
intChonSu_count(intChonSu[],intn,intPos_p,intPos_q){
//CountChonSubetweenfamilymemberpandq
intnew_index,old_index;
//theindexoffoldedandoriginalfamilytree
intnew_length=n;
//thenumberoffamilymembersinfoldedfamilytree
intnewPos_p=Pos_p,newPos_q=Pos_q;
//IndicatetheancestorsofPos_pandPos_qinfoldedfamilytree
intdistance=0;
//distancebetweentwomembers
while(Pos_q!
=Pos_p){
new_index=0,old_index=0;//InitilizetheindextoscantheChonSusequencefrombeginning
while(old_index<=n-2){
//goovertheunfoldedfamilytreeandfindwheretheChonSuequals2
if(ChonSu[old_index]!
=2)ChonSu[new_index]=ChonSu[old_index],new_index++,old_index++;
else{
//foldthefamilytreebyunitethememberwiththesameparents
if(new_index>0)ChonSu[new_index-1]--;
if(old_index//forthemembersaside,ChonSushouldminus2
if(Pos_p==old_index+1||Pos_p==old_index+2)newPos_p=new_index+1,distance++;
if(Pos_p>old_index+2)newPos_p--;
if(Pos_q==old_index+1||Pos_q==old_index+2)newPos_q=new_index+1,distance++;
//whenporqgoesuponelevel,increasethecounteroftheirdistance
if(Pos_q>old_index+2)newPos_q--;
//findoutthenewpositionoffamilymemberpandqinthefoldedfamilytree
old_index++;//checkupnextChonSu
new_length--;//foldthefamilytree
}
}
Pos_p=newPos_p;//initializationforanewtimeofscanning
Pos_q=newPos_q;
n=new_length;
}
returndistance;//whenpandqmeets,returnthedistancebetweenthem
}
voidmain(){
ifstreamtestopen("sample_input.txt",ios:
:
in);
if(!
testopen){
cerr<<"文件不存在"<exit
(1);
}
ofstreamoutput("output.txt",ios:
:
out);
intnoc;//numberofcases
testopen>>noc;
intn;//numberoffamilymembers
intk;//indexofchonsu
intp,q;//positionoffamilymembers
intdistance;//distancebetweenfamilymembers
while(noc>0){
testopen>>n;
int*chonsu=newint[n-1];
for(k=0;ktestopen>>chonsu[k];
testopen>>p>>q;
distance=ChonSu_count(chonsu,n,p,q);
output<noc--;
}
}
第六章:
集合与字典
1.设有1000个值在1~10000的整数,试设计一个利用散列方法的算法,以最少的数据比较次数和移动次数对它们进行排序。
1.
【解答1】
建立TableSize=10000的散列表,散列函数定义为
intHashTable:
:
FindPos(constintx){returnx-1;}
相应排序算法基于散列表类
#defineDefaultSize10000
#definen1000
classHashTable{//散列表类的定义
public:
enumKindOfEntry{Active,Empty,Deleted};//表项分类(活动/空/删)
HashTable():
TableSize(DefaultSize){ht=newHashEntry[TableSize];}//构造函数
~HashTable(){delete[]ht;}//析构函数
voidHashSort(intA[],intn);//散列法排序
private:
structHashEntry{//散列表的表项定义
intElement;//表项的数据,整数
KindOfEntryinfo;//三种状态:
Active,Empty,Deleted
HashEntry():
info(Empty){}//表项构造函数
};
HashEntry*ht;//散列表存储数组
intTableSize;//数组长度
intFindPos(intx);//散列函数
};
voidHashTable:
:
HashSort(intA[],intn){//散列法排序
for(inti=0;iintposition=FindPos(A[i]);
ht[position].info=Active;ht[position].Element=A[i];
}
intpos=0;
for(inti=0;iif(ht[i].info==Active)
{cout<}
【解答2】
利用开散列的方法进行排序。
其散列表类及散列表链结点类的定义如下:
#defineDefaultSize3334
#definen1000
classHashTable;//散列表类的前视声明
classListNode{//各桶中同义词子表的链结点(表项)定义
friendclassHashTable;
private:
intkey;//整数数据
ListNode*link;//链指针
public:
ListNode(intx):
key(x),link(NULL){}//构造函数
};
typedefListNode*ListPtr;//链表指针
classHashTable{//散列表(表头指针向量)定义
public:
HashTable(intsize=DefaultSize)//散列表的构造函数
{TableSize=size;ht=newListPtr[size];}//确定容量及创建指针数组
voidHashSort(intA[];intn)
private:
intTableSize;//容量(桶的个数)
ListPtr*ht;//散列表定义
intFindPos(intx){returnx/3;}
}
voidHashTable:
:
HashSort(intA[];intn){
ListPtr*p,*q;inti,bucket,k=0;
for(i=0;ibucket=FindPos(A[i]);//通过一个散列函数计算桶号
p=ht[bucket];q=newListNode(A[i]);
if(p==NULL||p->key>A[i])//空同义词子表或*q的数据最小
{q->link=ht[bucked];ht[bucked]=q;}
elseif(p->link==NULL||p->link->key>A[i])
{q->link=p->link;p->link=q;}
elsep->link->link=q;//同义词子表最多3个结点
}
for(i=0;ip=ht[i];
while(p!
=NULL){
cout<key<key;k++;
p=p->lin