2024.7.22练习

使用栈 实现进制转换

头文件 .h文件
#ifndef HAHA_H
#define HAHA_H
#include <myhead.h>
typedef int datatype; //数据类型
#define MAX 20        //顺序栈最大容量
typedef struct
{
    datatype *data; //存储栈的容器,指向堆区空间
    int top;        //记录栈顶元素的下标
} Stack, *StackPtr;

//创建栈
StackPtr stack_create();
//判空
int stack_empty(StackPtr S);
//判满
int stack_full(StackPtr S);
//入栈
void stack_push(StackPtr S, datatype e);
//出栈
void stack_pop(StackPtr S);
#endif
函数的封装 .c文件
#include "1.h"
//创建栈
StackPtr stack_create()
{
    //在堆区申请一个栈的大小
    StackPtr S = (StackPtr)malloc(sizeof(Stack));
    if (NULL == S)
    {
        printf("创建失败\n");
        return NULL;
    }
    //程序执行至此,表示栈申请出来了,但是存储栈的空间没有申请
    S->data = (datatype *)malloc(sizeof(datatype) * MAX);
    if (NULL == S->data)
    {
        printf("创建失败\n");
        return NULL;
    }
    //给空间内容初始化
    //memset(S->data,0,sizeof(datatype)*MAX);
    bzero(S->data, sizeof(datatype) * MAX);
    //栈顶元素变量初始化
    S->top = -1;
    printf("创建成功\n");
    return S;
}
//判空
int stack_empty(StackPtr S)
{
    return S->top == -1;
}
//判满
int stack_full(StackPtr S)
{
    return S->top ==MAX - 1;
}
//入栈
void stack_push(StackPtr S, datatype e)
{
    //判断逻辑
    if (NULL == S || stack_full(S))
    {
        printf("入栈失败\n");
        return;
    }
    //入栈逻辑
    S->top++;            //偏移栈顶数据
    S->data[S->top] = e; //将数据压入栈中

    //printf("入栈成功\n");
}
//出栈
void stack_pop(StackPtr S)
{
    //判断逻辑
    if (NULL == S || stack_empty(S))
    {
        printf("出栈失败\n");
        return;
    }
    //出栈逻辑:先弹后减
    printf("%d出栈成功\n", S->data[S->top]);
    S->top--;
}
主函数 main.c
#include <myhead.h>
#include "1.h"
int main()
{
    //调用创建函数,创建一个栈
    StackPtr S = stack_create();
    if (NULL == S)
    {
        return -1;
    } 
    //进制转换
    int a = 0;
    int b = 0;
    printf("请输入一个整数和进制数(进制数应在2到16之间): ");
    scanf("%d %d", &a, &b);

    // 验证进制数是否在有效范围内
    if (b < 2 || b > 16)
    {
        printf("进制数必须在2到16之间\n");
        return 0;
    }
    int count = 0;
    while (a > 0)
    {
        int c = a % b;
        if (c < 10)
        {
            stack_push(S, c); // 直接存储数字
        }
        else
        {
            // 对于10以上的数字,转换为对应的字符(A-F)
            stack_push(S, c - 10 + 'A');
        }
        a = a / b;
        count++;
    }
    //出栈
    printf("转换后的%d进制数为: ", b);
    for (int i = 0; i < count; i++)
    {
        if (S->data[S->top] >= 'A')
        {
            // 如果是字符,直接打印
            printf("%c", S->data[S->top]);
        }
        else
        {
            // 如果是数字,转换为字符后打印
            printf("%d", S->data[S->top]);
        }
        S->top--;
    }
    printf("\n");
    return 0;
}

用循环列表实现约瑟夫环

#include <stdio.h>  
#include <stdlib.h>  
  
// 链表节点定义  
typedef struct ListNode {  
    char data;  
    struct ListNode *next;  
} ListNode;  
  
// 创建一个新节点  
ListNode* createNode(char data) {  
    ListNode *newNode = (ListNode*)malloc(sizeof(ListNode));  
    if (!newNode) return NULL;  
    newNode->data = data;  
    newNode->next = NULL;  
    return newNode;  
}  
  
// 将节点插入到循环链表的尾部  
void insertTail(ListNode **head, char data) {  
    ListNode *newNode = createNode(data);  
    if (!*head) {  
        *head = newNode;  
        newNode->next = *head; // 使其成为循环链表  
    } else {  
        ListNode *temp = *head;  
        // 找到尾节点  
        while (temp->next != *head) {  
            temp = temp->next;  
        }  
        temp->next = newNode;  
        newNode->next = *head; // 连接到头节点,形成循环  
    }  
}  
  
// 约瑟夫环问题的解决方案  
char josephus(ListNode **head, int n, int m) {  
    if (!head || !*head || n < 1 || m < 1) return '\0';  
  
    ListNode *prev = NULL, *current = *head, *tail = NULL;  
  
    // 找到尾节点  
    for (int i = 0; i < n - 1; i++) {  
        tail = current;  
        current = current->next;  
    }  
  
    // 开始删除节点  
    while (current != current->next) { // 当链表中不止一个节点时  
        // 计数到 m-1  
        for (int count = 0; count < m - 1; count++) {  
            prev = current;  
            current = current->next;  
        }  
  
        // 删除当前节点  
        prev->next = current->next;  
  
        // 如果当前节点是尾节点,则更新尾节点  
        if (current == tail) {  
            tail = prev;  
        }  
  
        // 释放内存  
        free(current);  
        current = prev->next; // 移动到下一个要删除的节点  
    }  
  
    // 链表中只剩下一个节点,即最后的赢家  
    char winner = current->data;  
    free(current); // 释放最后一个节点  
    *head = NULL; // 重置头指针(可选)  
    return winner;  
}  
  
int main() {  
    ListNode *head = NULL;  
    int n, m;  
    char data;  
  
    printf("输入环的长度: ");  
    scanf("%d", &n);  
  
    printf("输入步长: ");  
    scanf("%d", &m);  
  
    printf("依次输入环内数据:\n");  
    for (int i = 0; i < n; i++) {  
        scanf(" %c", &data); // 注意前面有个空格来跳过任何之前的换行符  
        insertTail(&head, data);  
    }  
  
    printf("环内数据为: ");  
    ListNode *temp = head;  
    if (head) {  
        do {  
            printf("%c ", temp->data);  
            temp = temp->next;  
        } while (temp != head);  
        printf("\n");  
    }  
  
    char winner = josephus(&head, n, m);  
    printf("最后留下的赢家为: %c\n", winner);  
  
    return 0;  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值