数到三的人退出(链表实现)

链表的实现

昨天复习了这一周比较生疏的习题。而最后一个习题:有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号。
昨天通过数组完成,今天自己想通过循环单链表完成此习题。逻辑上这样比较简单。只需要每次计数到3的倍数就将该节点删除。
#include <stdio.h>
#include <stdlib.h>
#define LEN 5

class LinkNode{
public:
    LinkNode * next;
    int data;
};

LinkNode* insert(LinkNode* h,int value){
    LinkNode* pLinkNode=NULL;
    LinkNode* p=h;
    pLinkNode = (LinkNode*)malloc(sizeof(LinkNode));

    pLinkNode->data=value;
    pLinkNode->next=h;

    if(h==NULL){
        h=pLinkNode;
        h->next=pLinkNode;
        return pLinkNode;
    }

    while(p->next!=h){
        p=p->next;
    }
    p->next=pLinkNode;
    return pLinkNode;
}

void deleteNode(LinkNode* dp){//删除操作是否要传指针的指针呢? 如果使用**则是对传入指针本身操作
    //单链表删除必须找到删除节点的前一个节点 传入参数是使用删除节点的前一个节点

    LinkNode *r= dp->next->next;
    LinkNode *q= dp;

        dp=dp->next;//必须先找到该删除节点,不能和下面一句换位
        printf ("%d号退出 \n",dp->data) ;
        q->next=r;          
        free(dp);//free函数执行以后dp的值不是NULL 而是feeefeee
        dp=NULL;//这里并不能将主函数中的要删除元素置为NULL,因为dp和p并不是同一个指针,只是dp与p指向同一片内存空间
}

void deleteRealNode(LinkNode** dp){//删除操作是否要传指针的指针呢? 如果使用**则是对传入指针本身操作
    //单链表删除必须找到删除节点的前一个节点 传入参数是使用删除节点的前一个节点

    LinkNode *r=(*dp)->next->next;
    LinkNode *q= *dp;

        *dp=(*dp)->next;//必须先找到该删除节点,不能和下面一句换位
        q->next=r;          
        free(*dp);//free函数执行以后dp的值不是NULL 而是feeefeee
        *dp=NULL;
}
LinkNode* creatList(int len){
    LinkNode *head=NULL;
    LinkNode *p=head;
    int n=1;

    head=insert(head,n++);
    head->next=head;

    while(n<=len){
        p=insert(head,n++);
        p=p->next;
    }
    return head;
}

int main(){
    LinkNode* head=creatList(LEN);
    LinkNode* p=head;
    LinkNode* q=NULL;

    while(1){
            q=p->next;
            deleteNode(q);
            if(p->next==(LinkNode*)0xfeeefeee)      //采用了第一种传入一级指针
                break;
            /*if(p->next==NULL)
                break;
                这种方法在传入**是依然失效,因为这里必须传入的是要删除节点的前一个节点,真正操作的只能是该节点而不能对要删除的节点进行操作
            */
            p=p->next->next;//后移指针必须在删除节点完成以后
    }
    printf("winner is %d",q->data);
    system("pause");
    return 0;
}
附上同桌的代码参考一下:
#include <stdio.h>
#include <stdlib.h>

typedef struct people
{
    int num ;
    struct people *next ;
}people ;

people *insert_new ()
{
    people *p ;

    p = (people *)malloc(sizeof (people)) ;

    return p ;
}

int main ()
{
    int i , num , count = 1 ;
    people *a , *h ;

    printf ("输入人数:") ;
    scanf ("%d" , &num) ;

    a = h = (people *)malloc(sizeof (people)) ;

    a ->num = 1 ;
    i= 2 ;

    while (i <= num)
    {
        a ->next = insert_new() ;
        a = a ->next ;
        a ->num = i ;
        i++ ;
    }

    a ->next = h ;

    while ( h ->next != h)
    {
        if (count == 2)
        {
            printf ("%d退出\n" , h ->next ->num) ;
            h ->next = h ->next ->next ;//报数为3的退出,重新开始计数。
            count = 0 ;
        }
        h = h ->next ;
        count++ ;
    }

    printf ("最后剩下的人序号为%d\n" , h ->num) ;

    return 0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值