单循环链表练习

链表有环的定义:链表的末尾指向了链表内的某个节点。

附:约瑟夫问题

#include "stdio.h"
#include "stdbool.h"
#include "stdlib.h"
#include "stdarg.h"
#include "string.h"
#include "math.h"
#include "time.h"
#include "errno.h"

typedef int Status;
typedef int Elemtype;

typedef struct node
{
    Elemtype data;
    struct node *next;
}Node;

typedef struct node* LinkCList;

void CycleListInit(LinkCList *CL);
void CycleListInsert(LinkCList *CL,int i);
void CycleListDelete(LinkCList *CL,int i);
void printfCList(LinkCList CL);
void Josephus(LinkCList *CL,int n);

//  scanf(“%*[^\n]%*c”)} == fflush(stdin),刷新输入缓存区(去除非法字串)
//  ^表示"非",[^\n]表示读入换行字符就结束读入。这个是scanf的正则用法,我们都知道scanf不能接收空格符,但是使用%[^\n]就可以了。
//  *表示该输入项读入后不赋予任何变量,即scanf("%*[^\n]%*c")表示跳过一行字符串。

int main(void)
{
    LinkCList L = NULL;
    LinkCList L1 = NULL;
    int i,num;
    char ch;
    printf("1.初始化结点\n2.插入结点\n3.删除结点\n4.打印该单循环链表\n5.约瑟夫问题\n(输入q退出)\n");

    while(ch != '0')
    {
        scanf("%c",&ch);
        switch(ch)
        {
            case '1':
                CycleListInit(&L);
                printfCList(L);
                putchar('\n');
            break;

            case '2':
                printf("输入要插入结点的位置:");
                scanf("%d",&i);
                CycleListInsert(&L,i);
                printfCList(L);
                putchar('\n');
            break;

            case '3':
                printf("输入要删除结点的位置:");
                scanf("%d",&i);
                CycleListDelete(&L,i);
                printfCList(L);
                putchar('\n');
            break;

            case '4':
                printfCList(L);
                putchar('\n');
            break;
			
			 case '5':
                printf("本次约瑟夫环共有多少位元素?\n");
                scanf("%d",&num);
                Josephus(&L1,num);
            break;

            case 'q':
            exit(0);

        }
    }
    return 0;
}


void CycleListInit(LinkCList *CL)
{
    LinkCList temp , rear;
    Elemtype i;

    printf("输入结点的值,输入0则完成初始化\n");

    while(1)
    {
        scanf("%d",&i);
        //fflush(stdin);
        scanf("%*[^\n]%*c");
        srand(time(0));
        if(i == 0)
        {
            return;
        }

        if((*CL) == NULL)//空表
        {
            *CL = (LinkCList)malloc(sizeof(Node));
            if(!(*CL))
            {
                printf("内存创建失败");
                exit(1);
            }
            (*CL)->data = i;
            (*CL)->next = *CL;
        }
        else
        {
            for(rear = (*CL); rear->next != (*CL);rear = rear->next);//找到末尾结点

            temp = (LinkCList)malloc(sizeof(Node));
            if(!temp)
            {
                printf("内存创建失败");
                exit(1);
            }
            temp->data = i;
            temp->next = *CL;//新结点指向头
            rear->next = temp;//原来末尾的指向新结点
        }
    }
}

void CycleListInsert(LinkCList *CL,int i)
{
    LinkCList temp,rear,newnode;
    int j,newdata;

    printf("输入插入结点的值:");
    scanf("%d",&newdata);

    if(i == 1)
    {
        newnode = (LinkCList)malloc(sizeof(Node));
        if(!newnode)
        {
            printf("插入结点内存分配失败\n");
            exit(1);
        }
        newnode->data = newdata;
        for(rear = *CL;rear->next != *CL;rear = rear->next);
        newnode->next = *CL;
        rear->next = newnode;
        *CL = newnode;
    }
    else
    {
        temp = *CL;
        for(j = 1; j < i-1;j++)
        {
            temp = temp->next;
        }
        newnode = (LinkCList)malloc(sizeof(Node));
        if(!newnode)
        {
            printf("插入结点内存分配失败\n");
            exit(1);
        }
        newnode->data = newdata;
        newnode->next = temp->next;
        temp->next = newnode;
    }
}

void CycleListDelete(LinkCList *CL,int i)
{
    LinkCList temp,target;
    int j = 1;

    if(i == 1)
    {
        for(target = *CL;target->next != *CL;target = target->next);
        temp = *CL;
        *CL = (*CL)->next;
        target->next = *CL;
        free(temp);
    }
    else
    {
        target = *CL;
        for(j = 1; j < i-1;j++)
        {
            target = target->next;
        }
        temp = target->next;
        target->next = temp->next;
        free(temp);
    }

}

void printfCList(LinkCList CL)
{
    LinkCList temp = CL;
    if(!temp)
    {
        printf("该链表为空");
    }
    else
    {
        do
        {
            printf("%d ",temp->data);
        }while((temp = temp->next) != CL);
    }
    putchar('\n');
}

void Josephus(LinkCList *CL,int n)
{
    LinkCList temp,rear,now;
    int i,m = 3;

    if(n < 1)
    {
        return;
    }
    *CL = (LinkCList)malloc(sizeof(Node));
    (*CL)->data = 1;
    (*CL)->next = *CL;

    for(rear = *CL;rear->next != *CL;rear = rear->next);

    for(i = 1;i < n;i++)
    {
        temp = (LinkCList)malloc(sizeof(Node));
        temp->data = i+1;
        rear->next = temp;
        temp->next = *CL;
        rear = temp;
    }

    m %= n;//求余
    now = *CL;
    while(now != now->next)
    {
        for(i = 1;i < m-1 ;i++)//每次找到要删除的前一个结点
        {
            now = now->next;
        }
        printf("%d->",now->next->data);
        now->next = now->next->next;
        now = now->next;
    }
    printf("%d\n",now->data);

    return;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值