数据结构例题(C语言)——纸牌问题

本文介绍了一道关于数据结构的纸牌问题,使用C语言进行求解。当桌上剩余至少三张牌时,连续扔掉前两张,并将最新一张移到牌尾。举例说明了操作过程及输出结果,包括扔掉的牌号和最终剩余的牌号。
摘要由CSDN通过智能技术生成

桌上有一叠牌,从第一张牌(即位于顶面的牌)开始从上往下依次编号为1~n。当至少还剩三张牌时进行以下操作:把第一、二张牌扔掉,然后把当前状态下新的第一张放到整叠牌的最后。输入n,输出每次扔掉的牌,以及最后剩下的牌。 输入输出样例如下:

输入4

第一次:扔掉1,2

从顶向底最后剩下:4,3

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

#define OK 1
#define ERROR 0

typedef int ElemType;
typedef int status;


typedef struct Qnode//链表结点 
{
    ElemType data;//数据域 
    struct Qnode *next;//指向下一个结点 
}Qnode;

typedef struct link_queue//链队
{
    Qnode *front,*rear;//链队的头指针和尾指针
    int size=0;//链队长度 
}Link_Queue;

//1.链队列初始化
status Init_Link_Queue(Link_Queue *Q)
{
    Q=(Link_Queue*)malloc(sizeof(Link_Queue));//开辟链队指针结点
    if(!Q)
    {
        printf("初始化链队指针结点失败\n");
        exit(0);//初始化链队指针结点失败,退出程序 
    }
} 
//2.初始化 
status Init_Qnode(Link_Queue *Q,Qnode *P)
{
    P=(Qnode*)malloc(sizeof(Qnode));//开辟头结点
    if(!P)
    {
        printf("初始化头结点失败\n");
        exit(0);//初始化头结点失败,退出程序 
    }
    P->next=NULL;//头节点指向空 
    P->data=0; //头数据域为零 
    Q->front=Q->rear=P;//将头尾指针指向头链表 
} 

//3.链队列的扩容操作
status Expansion_Queue(Link_Queue *Q)
{
    
    Qnode *P;
    P=(Qnode*)malloc(sizeof(Qnode));//开辟新结点
    if(!P)
    {
        printf("开辟新结点失败\n");
        return ERROR;//开辟新结点失败,退出程序 
    }
    Q->rear->next=P;//将新结点挂在链表上 
    P->next=NULL;//新结点的next指向空 
    P->data=0;//新结点数据域为零 
    Q->rear=Q->rear->next;//头指针后移 
    return OK;
}

//4.链队列的入队操作
status Push_Queue(Link_Queue *Q,ElemType e) 
{
    if(!Expansion_Queue(Q))//判断是否需要扩容,并扩容 
        exit(0);
    Q->rear->data=e;//将数据放入数据域 
    Q->size++;//记录存储数据量 
    return OK;
}

//5.出队列 
status Delete_Queue(Link_Queue *Q,ElemType *e) 
{
    Qnode *p;
    if(Q->front==Q->rear)//判断结点是否为空 
    {
        return ERROR;
    }
    p=Q->front->next;
    *e=p->data;//将数据传给*e 
    Q->front->next=p->next;//头指针后移 
    if(p==Q->rear)//p和尾指针地址相同时尾指针归零(指向头指针的指向) 
    Q->rear=Q->front;
    free(p);//释放空间 
    return OK;
}
//6.链队列的撤销
status Destroy_Link_Queue(Link_Queue *Q)//从头开始依次释放 
{
    Qnode *p,*q;
    p=Q->front;
    q=p->next;
    while(1)
    {
        if(Q->rear==p)//如果尾指针和p(头指针) 同时指向同一块空间释放掉,直接结束程序 
        {
            free(p);
            break;
        }
        free(p);//释放空间 
        p=q;//将头指针指向下一个结点 
        q=q->next;
    }
     printf("链队列撤销完成"); 
}
    
//7.判断
status Judgement_Queue(Link_Queue *Q)
{
    Qnode *p;
    int i,j=0; 
    while(Q->size>3)//判断是否剩最后三张牌 
    {
        i=2;
        j++;
        printf("第%d次撤销",j); 
        while(i)//两次循环撤掉前两空间 
        {
            p=Q->front->next;//首元节点没有存数据,从下一个结点开始 
            Q->front->next=p->next;//将指针指向下一个结点 
            printf(" %d ",p->data);
            free(p);
            Q->size--; //数据量减少 
            i--;
        }
        printf("\n");
        Q->rear->next=Q->front->next;//将有数据的第一个结点放到队尾 
        Q->front->next=Q->front->next->next;
        Q->rear=Q->rear->next;
        Q->rear->next=NULL;
    }
} 

int main()
{
    Link_Queue Q;//定义头指针结点  
    Qnode P;//定义存数据结点 
    ElemType e;
    Init_Link_Queue(&Q);//头指针的初始化 
    Init_Qnode(&Q,&P);//数据指针的初始化 
    
    printf("请输入数据\n");
    scanf("%d",&e);
    for(int i=1;i<=e;i++)//利用循环实现数据的输入 
        Push_Queue(&Q,i);//调用入队函数 
        
    Judgement_Queue(&Q);
    
    while(1)//利用循环实现数据的输出 
    {
        if(!Delete_Queue(&Q,&e))
            break;
        printf("%d ",e);
    }
    printf("\n");
    Destroy_Link_Queue(&Q);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值