You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于栈的N皇后问题C语言实现:段错误(核心已转储)排查求助

解决N皇后栈实现中的段错误问题

首先咱们先定位你遇到的**段错误(segmentation fault)**的直接原因,再梳理代码里的其他逻辑问题,最后给出修正后的完整代码。

导致段错误的核心问题

你在isValid函数里的这段代码是罪魁祸首:

for (int i = sizeof(colStore)-1; i>=0; i--) {
 push(ptt,colStore[i]);
}

sizeof(colStore)返回的是数组的总字节数,而非数组的元素个数。比如如果colStore是包含3个int的数组(假设int占4字节),sizeof(colStore)会返回12,这时候i从11开始循环,访问colStore[11]完全是越界操作——这会破坏栈的内部数据,导致后续row或者colStore[i]变成非法值,最终在arr[row][colStore[i]]这行触发段错误。

正确的做法是用栈的大小(也就是Size变量)来作为数组的元素个数,循环应该改成:

for (int i = Size-1; i >= 0; i--) {
 push(ptt, colStore[i]);
}

代码里的其他逻辑错误

除了段错误,你的代码还有几个会导致功能失效的问题:

  1. isValid函数里错误重置currentPosition
    你在函数开头写了currentPosition=0;,这会把传入的当前列位置直接覆盖成0,导致永远只判断第0列是否合法,完全不符合逻辑,必须删掉这行。

  2. print函数里的newStruct拼写错误
    你调用了newStruct(n),但你的栈创建函数是newStack,这里应该改成newStack(n),否则会因为未定义函数导致编译错误。

  3. isValid函数中不必要的二维数组arr
    其实不需要创建整个二维数组来判断斜线冲突,我们可以直接通过栈里存储的列位置和当前位置计算斜线关系,这样能简化代码,避免数组越界风险。

修正后的完整代码

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <math.h>

struct stack {
    int maxsize;
    int top;
    int *items;
};

struct stack* newStack(int capacity) {
    struct stack *pt = (struct stack*)malloc(sizeof(struct stack));
    pt->maxsize = capacity;
    pt->top = -1;
    pt->items = (int*)malloc(sizeof(int) * capacity);
    return pt;
}

int size(struct stack *pt) {
    return pt->top + 1;
}

int isEmpty(struct stack *pt) {
    return pt->top == -1;
}

int isFull(struct stack *pt) {
    return pt->top == pt->maxsize - 1;
}

void push(struct stack *pt, int x) {
    if (isFull(pt)) {
        printf("\nOverflow");
        exit(EXIT_FAILURE);
    }
    pt->items[++pt->top] = x;
}

int peek(struct stack *pt) {
    if (!isEmpty(pt)) {
        return pt->items[pt->top];
    } else {
        exit(EXIT_FAILURE);
    }
}

int pop(struct stack *pt) {
    if (isEmpty(pt)) {
        printf("\nUnderflow");
        exit(EXIT_FAILURE);
    }
    return pt->items[pt->top--];
}

void print(struct stack *s, int n) {
    int Size = size(s);
    struct stack *temp = newStack(n);
    // 先把栈元素弹出到临时栈,同时打印
    for (int i = 0; i < Size; i++) {
        int col = pop(s);
        push(temp, col);
        for (int j = 0; j < n; j++) {
            if (j == col) {
                printf("Q ");
            } else {
                printf("* ");
            }
        }
        printf("\n");
    }
    // 把元素放回原栈
    while (!isEmpty(temp)) {
        push(s, pop(temp));
    }
    printf("\n");
}

bool isValid(struct stack *ptt, int currentPosition, int n) {
    if (isEmpty(ptt)) {
        return true;
    }

    int Size = size(ptt);
    int colStore[Size];
    bool isvalid = true;

    // 弹出栈元素,检查列冲突,同时保存列位置
    for (int i = 0; i < Size; i++) {
        int col = pop(ptt);
        colStore[i] = col;
        if (col == currentPosition) {
            isvalid = false;
        }
    }

    // 把元素放回栈
    for (int i = Size - 1; i >= 0; i--) {
        push(ptt, colStore[i]);
    }

    if (!isvalid) {
        return false;
    }

    // 检查斜线冲突:当前位置是第 (n - Size - 1) 行,currentPosition 列
    int currentRow = n - Size - 1;
    for (int i = 0; i < Size; i++) {
        int existingRow = n - Size + i;
        int existingCol = colStore[i];
        // 斜线判断:行差的绝对值等于列差的绝对值
        if (abs(currentRow - existingRow) == abs(currentPosition - existingCol)) {
            return false;
        }
    }

    return true;
}

int solve(struct stack *p, int n) {
    int currentPosition = 0;
    int counter = 0;

    while (true) {
        bool isvalid = false;
        while (currentPosition < n) {
            if (isValid(p, currentPosition, n)) {
                push(p, currentPosition);
                currentPosition = 0;
                isvalid = true;
                break; // 找到合法列后,跳出循环处理下一行
            } else {
                currentPosition++;
            }
        }

        if (!isvalid) {
            if (isEmpty(p)) {
                printf("\nEnd");
                break;
            } else {
                currentPosition = pop(p);
                currentPosition++;
            }
        }

        if (size(p) == n) {
            print(p, n);
            currentPosition = pop(p);
            currentPosition++;
            counter++;
        }
    }

    if (counter > 0) {
        printf("\nNumber of solutions found: %d", counter);
    } else {
        printf("\nNo solution found");
    }
    return counter;
}

int main() {
    int n;
    printf("\nEnter n: ");
    scanf("%d", &n);
    struct stack *pt = newStack(n);
    solve(pt, n);
    // 释放内存,避免内存泄漏
    free(pt->items);
    free(pt);
    return 0;
}

关键修改说明

  1. 修复了sizeof(colStore)的错误,改用Size(栈的元素个数)来循环恢复栈元素。
  2. 删除了isValid函数中错误的currentPosition=0;赋值,保证判断的是传入的当前列。
  3. 替换了print函数里的newStruct为newStack。
  4. 简化了斜线冲突的判断逻辑,不需要创建二维数组,直接通过行号和列号的差值绝对值判断是否在同一条斜线上。
  5. 在main函数中添加了内存释放代码,避免内存泄漏。
  6. 在solve函数的合法列判断循环中添加了break,找到合法列后直接处理下一行,避免不必要的循环。

现在你可以编译运行这段代码,输入n的值(比如4),就能看到正确的N皇后解决方案了。

内容的提问来源于stack exchange,提问作者user16959642

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 15:17:32