练习(8-25)

11.已知二叉树以二叉链表存储,编写算法完成:对于树中每个元素值为x的结点,删去以它为根的子树,并释放相应空间

想法: 删除值x为根的子树,只要能删除左、右子树,就可以释放值为x的根结点,因此宜采用后序遍历。算法思想:删除值为x的根结点,将其父结点的左(右)子女指针置空,用层次遍历易于找到某结点的父结点。

void Delete(BiTree bt){
    if(bt){
        DeleteXTree(bt->lchild);
        DeleteXTree(bt->rchild); //删除bt左子树、右子树
        free(bt);
}
}
//在二叉树上擦护照所有以x为元素值的结点,并删除以其为根的子树
void Search(BiTree bt,Elemtype x){
    BiTree Q[];   //Q是存放二叉树根结点指针的队列
    if(bt){    
        if(b->data==x){    若根结点值为x,则删除整棵树
            DeleteXTree(bt);
            exit(0);
}
    Init Queue(Q);
    EnQueue(Q,bt);
    while(!IsEmpty(Q)){
        DeQueue(Q,p);
        if(p->lchild)    //若左子女非空
            if(p->child->data==x){    //左子树符合则删除左子树
                DeleteXTree(p->lchild);
                p->lchild=NULL;
}                                //父结点的左子女置空
    else
        EnQueue(Q,p->lchild);  //左子树入队列
    if(p->rchild)
        if(p->rchild->data==x){    //右子树符合则删除左子树
            DeleteXTree(p->rchild);
            p->rchild=NULL;
}
    else
        EnQueue(Q,p->rchild);    //右子女入队
}    
}
}

12、在二叉树中查找值为x的结点,试编写算法打印值为x的结点的所有祖先,假设值为x的结点不多于1个

解:采用非递归后序遍历,最后访问到根结点,访问的值为x的结点时,栈中所有元素均为该结点的祖先,依次出栈即可。

typedef struct{
    BiTree t;
    int tag;
}stack;  //tag=0表示左子女被访问,tag=1表示右子女被访问
void Search(BiTree bt,Elemtype x){
    //在二叉树bt,查找值为x的结点,并打印其所有祖先
    stack s[];
    top=0;
    while(bt!=NULL||>0){
        while(bt!=NULL && bt->data!=x){ //结点入栈
            s[++top].t=bt;
            s[top].tag=0;
            bt=bt->lchild;        //沿左分支向下
            
}
    if(bt->data==x){
        printf("所查结点的所有祖先结点的值为:\n");
        for(i=1;i<top;i++)
        printf("%d",s[i].t->data);
        exit(1);
}
while(top!=0 && s[top].tag==1)
    top--;        //退栈
    if(top!=0){
        s[top].tag=1;
        bt=s[top].t->rchild;    //沿分支向下遍历
}
}
}

13.设一棵二叉树的结点结构为(LLwINK,INFO,RLINK),ROOT为指向该二叉树根结点的指针,p和q分别为指向该二叉树中任意两个结点的指针,试编写算法ANCESTOR(ROOT,p,q,r),找到p和q的最近公共祖先结点r

算法思想:采用后序非递归算法,栈中存放二叉树结点的指针,当访问到某结点时,栈中所有元素均为该结点的祖先。

后序遍历必然先遍历到结点p,栈中元素均为p的祖先。

先将栈赋值到另一个辅助栈中。继续遍历到结点q时,将栈中元素从栈顶开始逐个到辅助栈中取匹配,第一个匹配的元素就是结点p和q的最近公共祖先

typedef struct{
    BiTree t;
    int tag;  //tag=0表示左子女已被访问,tag=1表示右子女已被访问
}stack;
stack s[],s1[];
BiTree Ancestor(BiTree ROOT,BiTnode *p,BiTNode *q){
    //求最近公共结点
    top=0;bt=ROOT;
    while(bt!=NULL || top>0){
        while(bt!=NULL){
            s[++top].t=bt;
            s[top].tag=0;
            bt=bt->lchild;
}
    while(top!=0 && s[top].tag==1){
    //假定p在q的左侧,遇到p时,栈中元素均为p的祖先
        if(s[top].t==p)
        for(i=1;i<top;i++)
            s1[i]=s[i];
            top1=top;
}
if(s[top].t==q)
    for(i=0;i>0;i--){    //将栈中元素的树结点到s1中去匹配
        for(j=top1;j>0;j--)
            if(s[j].==s[i].t)
                return s[i].t;   //p和q的最近公共祖先已找到
}
    top--;  //退栈
}
if(top!=0){
    s[top].tag=1;
    bt=s[top].t->rchild;
}            //沿右分支向下遍历
}
    return NULL;    //p和q公共祖先
}

14.顺序表操作实现

//顺序表动态存储初始化
void initList(SeqList& L){
    L.data=new DtaType[initSize];
    if(!L.data){  printf("分配错误\n");}
    L.maxSize;
    L.n=0;
}
//清空
void clearList(SeqList& L){
    L.n=0;
}
//求长度
void Length(SeqList& L){
    return L.n;
}
//判表空
int isEmpty(SeqList& L){
    return (L.n==0)?1:0;
}
//判断表满
int isFull(SeqList &L){
    return (L.n==L.maxSize)?1:0;
}
//查找
int Search(SeqList& L,DataType x){
    for(int i=1;i<L.n;i++)
        if(L.data[i-1]==x)
        return i;
    return 0;
}
//定位
int Locate(SeqList& L,int i){
    if(i>=1 && i<=L.n) return i;
    else
    return 0;
}
//顺序复制
void Copy(SeqList& L1,SeqList& L2){
//复制表L2的全部内容到表L1
    L1.maxSize=L2.maxSize;
    L1.n=L2.n;
if(!L1.data){
    L1.data=new DataType[L1.maxSize];
    if(!L1.data){
        cout<<"分配错误!";
        exit(1);
}
    for(int i=1;i<=L.n;i++)
        L1.data[i-1]=L2.data[i-1];
}
//插入
int Insert(SeqList& L,int i,DataType& x){
    //将元素x插入到表中第i个元素。若插入成功函数返回1,否则返回0
    if(L.n==L.maxSize) return 0; //表满,不能插入
    if(i<0 || i>L.n+1)    return 0;  //参数不合理,不可插入
    for(int j=L.n;j>=i;j--)
        L.data[j]=L.data[j-1];    //依次后移,空出第i号位置
    L.data[i-1]=x;    // 插入
    L.n++;
    return 1; //插入成功   
}
//顺序表删除算法
int Remove(SeqList& L,int i,DataType& x){
    if(!L.n) return 0;        //表空,不能删除
    if(i<1 ||i>L.n) return 0;    //参数i不合理,不能删除
    x=L.data[i-1];        //存被删元素的值
    for(int j=i;i<L.n;j++)
    L.data[j-1]=L.data[j];   //依次前移,填补
    L.n--;        //表长度减1
    return 1;    //删成功
}

15.不带头结点单链表的操作

//插入
int insert(LinkList& first,int i,DataType x){
    if(!first || i==1){
        LinkNode *newNode=new LinkNode;
        if(!=newNode){
        cerr<<"分配失败";
}
    newNode->data=x;
    newNode->link=first;
    first=newNode;    //新结点成为第一个结点
}else{
    LinkNode *p=first;
    int k=1;
    while(p!=NULL && k<i-1){
        p=p->link;k++;
}
    if(p==NULL && first){   //非空表且链太短
        cerr<<"无效的插入位置";
}else{
    LinkNode * newNode=new LinkNode;    //建立一个新结点
    if(p==NULL && first){
        cerr<<"分配错误";
    newNode->data=x;
    newNode->link=p->link;
    p->link=newNode;
}
}
}
    return 1; //正常插入
}
//删除
int remove(LinkList &first,i,DataType &x){
    LinkNode *q,*p;
    int k;
    if(i<=1){  //删首元结点时表头退到下一个结点
        q=first;
        first=first->link;
}else{
    p=first;
    k=1;
    while(p!==NULL ||p->link==NULL){ //空表或链太短
        cerr<<"无效删除位置";
}
q=p->link;        //保存第i号结点的位置
p->link=q->link;        //第i-1和第i+1号结点链接
}
x=q->data;
delete q;
return 1;
}

16.带头结点的单链表

//计算长度
int Length(LinkList &first){
    LinkNode *p=first->link;
    int count=0;
    while(p!=NULL)
        {p=p->link;count++}
    return count;
}
//search -value
LinkNode *Search(LinkList &first,DtaType x){
    LinkNode *p=first->link;
    while(p!=NULL && p->data!=x)
        p=p->link;
    return p;
}
//search -locate
LinkNode *locate(LinkList& first,int i){
    if(i<0) return NULL;   //找头结点时i=0,i<0不合理
    LinkNode *p=first;
    int k=0;
    while(p!=NULL && k<i){  //循环找第i个结点,k作节点计数
        p=p->link;
        k++;
}
return p;
}
//insert
int insert(LinkList &first,int i,DataType x){
    LinkNode *p=Locate(first,i-1);
    if(p==NULL) return 0;
    LinkNode *s=new LinkNode;
    if(!s){ cerr<<分配错误\n;}
    s->data=x;
    s->link=p->link;   p->link=s;  //将*s皆在*p之后
    return 1;
}
//remove
int remove(LinkList &first,int i,DataType){
    LinkNode *p=Locate(first,i-1);  //定位于第i-1个结点
    if(p==NULL || p->link==NULL) return 0;
    LinkNode *q=p->link;   //用q保存被删除结点地址
    p->link=q->link;        //重新链接,将被删结点从链表摘下
    x=q->data;  delete q;          //取出被删除结点中的数据,释放结点
    return 1;
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、二叉树(二) 1. 写法 (1)二叉树的直径定义为从根结点至叶子的最大路径长度。编写法,求二叉树(二叉链表)的直径。 (2)已知二叉树(二叉链表)根结点指针bt,树中两个结点的指针p、q。编写法求距离结点*p和*q最近的公共祖先的地址。 (3)已知二叉树(二叉链表)根结点指针bt,利用二叉树叶子结点的rchild指针域将所有叶子结点从左向右连接成一个单向链表法返回单向链表结点指针(即最左边第1个叶子结点的地址)。 2. 编程题 (1) 从键盘输入一个字符串(要求字符串中无重复字符),将串中字符当做完全二叉树的顺序存储结构,建立对应的完全二叉树二叉链表存储结构,输出先、中、后序遍历结果。 (2) 用先序遍历法建立二叉树二叉链表存储结构(结点数据域类型为char,输入字符序列用字符'#'表示NULL),实现中序线索化,并用非递归法输出中序遍历结果的正序和逆序序列。 二、图 1. 已知某无向图如下图所示。画出该图的多重邻接表存储结构示意图。根据该存储结构,写出从顶点v0出发,深度和宽度优先遍历顶点访问次序。 2.写一个法,判断无向图是否有环。法提要:深度优先遍历过程中,访问某顶点后,该顶点的邻接点中有已访问的顶点且该已访问邻接点不是该顶点的上一级递归出发顶点(即存在回边),则有环。 3.编程题: 建立无向图邻接表存储结构,输出深度和宽度优先遍历顶点访问次序。 4.编程题:建立AOE网络存储结构,计并输出ve[]和vl[]。 5.选作题*:法设计-已知AOE网络的邻接表存储结构G,ve[]和vl[]值已全部求取,写出法,输出所有关键路径。要求每条关键路径用源点至汇点的顶点序列(拓扑有序)表示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值