数据结构(栈 + 队列)
约瑟夫环问题解决方案(循环队列+顺序栈)
问题描述
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号