数据结构复习 | 选填板子

整理了数据结构课程期末常考的选填题,用C实现求解,方便考试快速解答~

一、二叉树的恢复

前+中->后

已知树的前序遍历和中序遍历序列,输出后序遍历序列。

例题:

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
struct TreeNode{
    int val;
    struct TreeNode *left,*right;
};

//接收一个子根,创造左右子树
void createTree(struct TreeNode **T,int *preOrder,int preStart,int preEnd,int *inOrder,int inStart,int inEnd)
{
    if(inStart>inEnd)
        return ;
    (*T)=(struct TreeNode *)malloc(sizeof(struct TreeNode));
    (*T)->val=preOrder[preStart];
    (*T)->left=(*T)->right=NULL;
    if(preStart==preEnd)
        return ;
    int headVal=preOrder[preStart];
    int index=0;
    while(inOrder[index]!=headVal)      //index指向子根
        index++;
    int n=index-inStart;
    createTree(&(*T)->left,preOrder,preStart+1,preStart+n,inOrder,inStart,index-1);
    createTree(&(*T)->right,preOrder,preStart+n+1,preEnd,inOrder,index+1,inEnd);
}
struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize)
{
    struct TreeNode *root=NULL;
    createTree(&root,preorder,0, preorderSize-1,inorder,0,inorderSize-1);
    return root;
}
void postTravel(struct TreeNode *root)
{
    if(root)
    {
        postTravel(root->left);
        postTravel(root->right);
        printf("%d ",root->val);
    }
}

int main(int argc, const char * argv[]) {
    
    int pre[100],in[100];
    int preSize,inSize;
    scanf("%d%d",&preSize,&inSize);     //先输入数组元素个数
    int i;
    for(i=0;i<preSize;i++)
        scanf("%d",&pre[i]);            //再输入前序序列
    for(i=0;i<inSize;i++)
        scanf("%d",&in[i]);             //再输入中序序列
    struct TreeNode *root=buildTree(pre,preSize,in,inSize);
    postTravel(root);                   //输出后序遍历结果
    
    return 0;
}

中+后->前

例题:

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
struct TreeNode{
    int val;
    struct TreeNode *left,*right;
};

struct TreeNode *travelTree(int *inorder, int inBegin, int inEnd, int *postorder, int postBegin, int postEnd){
    if(postBegin>postEnd)
        return NULL;    //没有元素

    struct TreeNode *root=(struct TreeNode *)malloc(sizeof(struct TreeNode));
    root->val=postorder[postEnd];
    root->left=NULL;
    root->right=NULL;
    
    if(postBegin==postEnd)
        return root;    //只有一个元素,就是根节点
 
    int inRoot;
    for(inRoot=inBegin;inorder[inRoot]!=postorder[postEnd];inRoot++)
        ;
    root->left=travelTree(inorder,inBegin,inRoot-1,postorder,postBegin,postBegin+inRoot-inBegin-1);
    root->right=travelTree(inorder,inRoot+1,inEnd,postorder,postBegin+inRoot-inBegin,postEnd-1);
    return root;
}
struct TreeNode* buildTree2(int* inorder, int inorderSize, int* postorder, int postorderSize){
    struct TreeNode *root=NULL;
    if(inorderSize)
        root=travelTree(inorder,0,inorderSize-1,postorder,0,postorderSize-1);
    return root;
}
void preTravel(struct TreeNode *root)
{
    if(root)
    {
        printf("%d ",root->val);
        preTravel(root->left);
        preTravel(root->right);
    }
}

int main(int argc, const char * argv[]) {
    
    int in[100],post[100];
    int inSize,postSize;
    scanf("%d%d",&inSize,&postSize);     //先输入数组元素个数
    int i;
    for(i=0;i<inSize;i++)
        scanf("%d",&in[i]);              //再输入中序序列
    for(i=0;i<postSize;i++)
        scanf("%d",&post[i]);            //再输入后序序列
    struct TreeNode *root=buildTree2(in,inSize,post,postSize);
    preTravel(root);                     //输出前序遍历结果
    
    return 0;
}

二、堆排序

下标从1起,输入一组数据,输出构成的大顶堆并排序。

例题:

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

void adjust(int a[],int i,int n)        //调整堆,i要调整的堆(可以是一小部分)的root下标
{
    int j,temp;
    temp=a[i];
    j=2*i;                          //j是i的左孩子
    while(j<=n)
    {
        if(j<n && a[j]<a[j+1])      //j是较大的那个子结点
            j++;
        if(temp>=a[j])              //已满足堆
            break;
        a[j/2]=a[j];                //父亲比孩子小,需要交换
        j=2*j;
    }
    a[j/2]=temp;
}
void heapSort(int a[],int n)
{
    int i,temp;
    for(i=n/2;i>=1;i--)     //初始化堆
        adjust(a,i,n);
    for(i=1;i<=n;i++)
        printf("%d ",a[i]);     //输出大顶堆
    for(i=n-1;i>=1;i--)
    {
        temp=a[i+1];
        a[i+1]=a[1];        //最大元素放队尾
        a[1]=temp;
        adjust(a,1,i);
    }
}

int main(int argc, const char * argv[]) {
    
    int dui[100];
    int n;
    scanf("%d",&n); //先输入元素个数
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&dui[i]);    //逐个输入
    }
    heapSort(dui,n);    //实现堆排序,过程中可以输出首次成的大顶堆//
    
    return 0;
}

三、出栈合理性判断

给出入栈出栈序列,判断出栈顺序是否合理,如果合理,求栈需要开多大。

例题:

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

int in[105];    //入栈序列
int out[105];   //出栈序列
int stack3[105];
int top3=-1;

int main(int argc, const char * argv[]) {
    
    int n;
    scanf("%d",&n); //输入元素个数
    int i,j,cnt=0;
    for(i=0;i<n;i++)
        scanf("%d",&in[i]); //输入入栈元素,保证各不相同
    for(j=0;j<n;j++)
        scanf("%d",&out[j]);//输入出栈元素,保证各不相同
    j=0;
    for(i=0;i<n;i++)
    {
        stack3[++top3]=in[i]; //当前元素进栈
        if(top3+1>cnt)
            cnt=top3+1;  //更新cnt
        while(top3>=0 && out[j]==stack3[top3])
        {
            printf("%d ",stack3[top3]);   //输出实际出栈序列
            j++;
            top3--;
        }
    }
    if(top3==-1)
        printf("\n%d",cnt); //输出最大栈容量
    else 
        printf("\n不合法"); //没有全部出栈,不合法
        
    return 0;
}

四、Josephus问题

n个人,从编号为k的人开始报数,数到m的人出列,他的下一个人从1开始报数,直到全部出列。输出淘汰序列。

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

typedef struct jnode{
    int num;
    struct jnode *next;
}*NodePtr;

void JosephusNode(int n,int m,int k)    //n个人,从编号为k的人开始报数,数到m的人出列
{
    NodePtr list=NULL,p=NULL,r=NULL;
    int i;
    for(i=1;i<=n;i++)
    {
        p=(NodePtr)malloc(sizeof(struct jnode));
        p->num=i;
        if(list==NULL)
            list=p;
        else
            r->next=p;
        r=p;
    }
    p->next=list;
    p=list;     //建立一个循环链表
    
    for(i=1;i<k;i++)    //p指向第一个出发结点
    {
        r=p;
        p=p->next;
    }
    
    while(p->next!=p)       //跳出循环时只剩一个结点
    {
        for(i=1;i<m;i++)    //该把p指的删掉
        {
            r=p;
            p=p->next;
        }
        r->next=p->next;
        printf("%4d",p->num);   //输出被删掉的结点号
        free(p);
        p=r->next;
    }
    printf("\nlast out: %4d\n",p->num);
}

int main(int argc, const char * argv[]) {
    
    int n,m;
    scanf("%d%d",&n,&m);    //输入
    JosephusNode(n,m,1);    //过程中输出淘汰成员
    
    return 0;
}

五、哈夫曼树

以一组权值构建哈夫曼树,求带权路径和。

例题:

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

struct hnode{  //树结点
    int val;    //自身值,也即权值
    struct hnode *lchild,*rchild;
    struct hnode *next;     //按频率(由小到大)排的链表
};

struct hnode *hroot;     //哈夫曼树根
struct hnode *hhead;     //head指向头节点,便于建树
int hcnt;

struct hnode *createHNode(int val)
{
    struct hnode *p=(struct hnode *)malloc(sizeof(struct hnode));
    p->val=val;
    p->lchild=p->rchild=p->next=NULL;
    return p;
}
void insertHLink(struct hnode *p)
{
    struct hnode *q;
    for(q=hhead;q->next && p->val>=q->next->val;q=q->next)
        ;
    p->next=q->next;
    q->next=p;
}
void hdfs(struct hnode *r,int step)     //当前在第step层,root为第1层
{
    if(r==NULL)
        return ;
    if(r->lchild==NULL && r->rchild==NULL)
    {
        hcnt+=(step-1)*r->val;
    }
    hdfs(r->lchild,step+1);
    hdfs(r->rchild,step+1);
}

int main(int argc, const char * argv[]) {
    
    int n;
    scanf("%d",&n);     //输入数据数
    int i,tmp;
    hhead=createHNode(824);
    for(i=0;i<n;i++)
    {
        scanf("%d",&tmp);   //依次输入数据
        struct hnode *p=createHNode(tmp);
        insertHLink(p);
    }
    while(hhead->next->next)
    {
        struct hnode *q1,*q2,*qq;
        q1=hhead->next;
        q2=hhead->next->next;
        qq=createHNode(q1->val+q2->val);
        qq->lchild=q1;
        qq->rchild=q2;
        hhead->next=q2->next;
        insertHLink(qq);
    }
    hroot=hhead->next;
    hdfs(hroot,1);
    printf("%d",hcnt);      //打印带权路径总和
    
    return 0;
}

六、队列个数

例题:

#include <stdio.h>

int main(int argc,const char *argv[]){
    int n;
    scanf("%d",&n);         //输入数据总数
    int in[105],out[105];   //out[i]是第i个出队元素对应的进队下标0~n-1

    //进队序列是:e1,e2,e3,e4,e5,e6,e7,e8,e9
    int i,j,k,w,temp;
    for(i=1;i<=n;i++)
        scanf("%d",&in[i]);  //输入入队序列
    for(i=1;i<=n;i++)        //出队序列是e8,e4,e2,e5,e3,e9,e1,e6,e7
    {
        scanf("%d",&temp);   //输入出队序列
        for(j=1;j<=n;j++)
        {
            if(temp==in[j])
            {
                out[i]=j;
                break;
            }
        }
    }
    int queue[25][25];
    int qtop=-1;
    for(i=0;i<25;i++)
    {
        for(j=0;j<25;j++)
            queue[i][j]=0;
    }
    queue[++qtop][0]=out[1];
    for(i=2;i<=n;i++)
    {
        k=-1;
        for(j=0;j<=qtop;j++)
        {
            w=0;
            while(queue[j][w+1])
                w++;
            if(out[i]>queue[j][w])
            {
                if(k==-1 || queue[j][0]>queue[k][0])    //更优,更新k
                    k=j;
            }
        }
        if(k==-1)       //需要新建队
            queue[++qtop][0]=out[i];
        
        else    //入已存在的队
        {
            j=1;
            while(queue[k][j]!=0)       //一定是插在队尾
                j++;
            queue[k][j]=out[i];
        }
    }
    for(i=0;i<=qtop;i++)
    {
        j=0;
        while(queue[i][j]!=0)
        {
            printf("%d ",queue[i][j]);      //把输出序列按队输出
            j++;
        }
        puts("");
    }
    return 0;
}
  • 测试样例

    输入:

    9
    1 2 3 4 5 6 7 8 9
    8 4 2 6 3 9 1 5 7
    

    输出:

    8 9 
    4 6 7
    2 3 5
    1
    
  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值