数据结构(栈 + 队列)
约瑟夫环问题解决方案(循环队列+顺序栈)
问题描述
n个人围成一圈,从1开始报数,数到k者出圈。要求:
- 输出完整出圈顺序
- 确定最后幸存者(栈顶)
- 确定倒数第二个出圈者(次栈顶)
实现思路
/*
           循环队列操作流程
           +---------------+
    出队 <--| 1 2 3 ... n |<-- 入队
           +---------------+
                 |
                 v 报数到k
           +---------------+
           | 顺序栈        |
           | 最后出圈者在顶|
           +---------------+
*/
数据结构设计
循环队列(LinkQueue)
typedef struct {
    int *data;      // 存储空间基址
    int front;      // 队头指针
    int rear;       // 队尾指针
    int maxSize;    // 队列容量
} LinkQueue;
// 初始化队列
Status InitQueue(LinkQueue *Q, int n) {
    Q->data = (int*)malloc(n * sizeof(int));
    if(!Q->data) return ERROR;
    Q->front = Q->rear = 0;
    Q->maxSize = n;
    return OK;
}
// 判空
Status QueueEmpty(LinkQueue *Q) {
    return Q->front == Q->rear;
}
// 入队
Status EnQueue(LinkQueue *Q, int e) {
    if((Q->rear + 1) % Q->maxSize == Q->front) 
        return ERROR; // 理论上不会发生
    
    Q->data[Q->rear] = e;
    Q->rear = (Q->rear + 1) % Q->maxSize;
    return OK;
}
// 出队
Status DeQueue(LinkQueue *Q, int *e) {
    if(QueueEmpty(Q)) return ERROR;
    
    *e = Q->data[Q->front];
    Q->front = (Q->front + 1) % Q->maxSize;
    return OK;
}
顺序栈(Sqstack)
typedef struct {
    int *data;      // 栈空间基址
    int top;        // 栈顶指针
    int capacity;   // 栈容量
} SqStack;
// 初始化栈
Status InitStack(SqStack *S, int n) {
    S->data = (int*)malloc(n * sizeof(int));
    if(!S->data) return ERROR;
    S->top = -1;
    S->capacity = n;
    return OK;
}
// 入栈
Status PushStack(SqStack *S, int e) {
    if(S->top >= S->capacity - 1) return ERROR;
    
    S->data[++S->top] = e;
    return OK;
}
// 出栈
Status PopStack(SqStack *S, int *e) {
    if(S->top == -1) return ERROR;
    
    *e = S->data[S->top--];
    return OK;
}
核心算法实现
Status Josephus(int n, int k) {
    LinkQueue Q;
    SqStack S;
    
    // 初始化数据结构
    InitQueue(&Q, n+1);  // 多留一个空间方便判断
    InitStack(&S, n);
    
    // 初始化队列
    for(int i = 1; i <= n; i++) {
        EnQueue(&Q, i);
    }
    
    // 约瑟夫环处理
    int count = 0;
    while(!QueueEmpty(&Q)) {
        int num;
        DeQueue(&Q, &num);
        count++;
        
        if(count == k) {
            PushStack(&S, num);
            count = 0;
        } else {
            EnQueue(&Q, num);
        }
    }
    
    // 输出结果处理
    printf("out sequence:\n");
    int* output = (int*)malloc(n * sizeof(int));
    for(int i = n-1; i >= 0; i--) {
        PopStack(&S, &output[i]);
    }
    for(int i = 0; i < n; i++) {
        printf("%d ", output[i]);
    }
    
    // 输出最后两个元素
    printf("\nthe winner is: %d\n", output[n-1]);
    printf("the last loser is: %d\n", output[n-2]);
    
    free(output);
    return OK;
}
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号