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

基于双向链表的栈实现C语言Hierholzer算法:段错误求助

Let's walk through the problems in your code and fix them one by one—your segfault and unexpected branch behavior stem from a few critical pointer and memory management issues, plus some logical flaws in your Hierholzer implementation.

1. Fixing push and pop Functions (Root Cause of Unexpected Branching)

Your stack operations are broken because of incorrect pointer handling:

  • You're passing node* head by value, so any changes to head inside push/pop don't affect the original pointer in the caller. This means your stack never actually gets initialized, leading to weird behavior like entering the else branch even when the stack is empty.
  • The condition if (*head == NULL) in push is invalid: head is a pointer, so *head is a node struct—you can't compare a struct to NULL (a pointer constant).

Corrected push and pop:

void push(int source, int num, node **head) {
    node *n = malloc(sizeof(node));
    if (n == NULL) {
        perror("Failed to allocate node");
        exit(EXIT_FAILURE);
    }
    n->num = num;
    n->l = NULL;
    n->done = 0;
    n->source = source;
    if (*head == NULL) {
        *head = n;
        (*head)->r = NULL;
    } else {
        n->r = *head;
        (*head)->l = n;
        *head = n;
    }
}

int pop(node **head) {
    if(*head == NULL) {
        return -1;
    } else {
        node *temp = *head;
        *head = (*head)->r;
        if (*head != NULL) {
            (*head)->l = NULL;
        }
        int num = temp->num;
        free(temp);
        return num;
    }
}

Now we pass a pointer to a pointer (node**) so changes to the head are reflected outside the function, and we check the pointer itself (*head == NULL) instead of the struct it points to.

2. Fixing the Segmentation Fault in read()

Your read() function has three major issues causing the segfault:

  • Uninitialized pointer l: node *l; is a wild pointer—it points to random memory. When you pass it to push, you're accessing invalid memory.
  • Returning a local array: node *adj[num]; is a stack-allocated array. When you return it, the array is destroyed, leaving a dangling pointer that causes undefined behavior.
  • Incorrect file reading loop: while(fscanf(f,"%s",c)) will loop infinitely if fscanf fails (e.g., reaches EOF). We need to check for EOF explicitly.
  • Broken adjacency list construction: Your current code reads each "x,y" string and pushes both numbers to the same list, which doesn't build a valid adjacency list for edges.

Corrected read():

node** read(int num) {
    char a[2000] = "Assignment1.txt", c[1000];
    FILE *f = fopen(a,"r");
    if (f == NULL) {
        perror("Failed to open file");
        exit(EXIT_FAILURE);
    }
    printf("Got file\n");
    
    // Dynamically allocate adjacency list (avoids dangling pointer)
    node **adj = malloc(num * sizeof(node*));
    if (adj == NULL) {
        perror("Failed to allocate adjacency list");
        fclose(f);
        exit(EXIT_FAILURE);
    }
    
    // Initialize all adjacency list heads to NULL
    for (int i = 0; i < num; i++) {
        adj[i] = NULL;
    }
    
    // Read edges correctly: each "x,y" is an edge from x to y
    while(fscanf(f,"%s",c) != EOF) {
        char *p = strtok(c, ",");
        if (p == NULL) continue;
        int source = atoi(p) - 1; // Convert to 0-indexed (since input is 1-indexed)
        if (source < 0 || source >= num) {
            fprintf(stderr, "Invalid vertex: %d\n", source + 1);
            continue;
        }
        p = strtok(NULL, ",");
        if (p == NULL) continue;
        int dest = atoi(p);
        push(source, dest, &adj[source]);
    }
    printf("Adjacency list created\n");
    fclose(f); // Don't forget to close the file!
    return adj;
}

We now dynamically allocate the adjacency list, initialize all pointers to NULL, read edges correctly, and add error checking for file operations and memory allocation.

3. Rewriting the euler() Function (Hierholzer Algorithm Fix)

Your original euler() function has uninitialized pointers and logical flaws that break the path construction. Here's a standard stack-based implementation of Hierholzer's algorithm that works correctly:

// Helper function to reverse the linked list (for correct path order)
node* reverse_list(node *head) {
    node *prev = NULL;
    node *current = head;
    node *next = NULL;
    while (current != NULL) {
        next = current->r;
        current->r = prev;
        prev = current;
        current = next;
    }
    return prev;
}

node* euler(node *adj[], int n, int start) {
    node *path = NULL;
    node *stack = NULL;
    
    // Push the start vertex (convert to 1-indexed for output)
    push(-1, start + 1, &stack);
    
    while (stack != NULL) {
        int current = stack->num - 1; // Convert back to 0-indexed for adjacency list
        node *temp = adj[current];
        
        // Find the first unvisited edge
        while (temp != NULL && temp->done == 1) {
            temp = temp->r;
        }
        
        if (temp != NULL) {
            temp->done = 1; // Mark edge as visited
            push(current, temp->num, &stack);
        } else {
            // Pop from stack and add to path
            int node_val = pop(&stack);
            push(-1, node_val, &path);
        }
    }
    
    // Reverse the path to get the correct order
    return reverse_list(path);
}

This implementation follows the standard Hierholzer workflow: use a stack to traverse edges, mark edges as visited, and build the path by popping nodes when no more unvisited edges exist.

4. Main Function and Cleanup

We'll add memory cleanup functions to avoid leaks, and error checking for user input:

// Helper function to free the adjacency list
void free_adjacency_list(node **adj, int num) {
    for (int i = 0; i < num; i++) {
        node *temp = adj[i];
        while (temp != NULL) {
            node *next = temp->r;
            free(temp);
            temp = next;
        }
    }
    free(adj);
}

// Helper function to free the path list
void free_path(node *path) {
    node *temp = path;
    while (temp != NULL) {
        node *next = temp->r;
        free(temp);
        temp = next;
    }
}

int main() {
    int n;
    printf("Enter the number of vertices: ");
    if (scanf("%d", &n) != 1 || n <= 0) {
        fprintf(stderr, "Invalid number of vertices\n");
        return EXIT_FAILURE;
    }
    node **adj = read(n);
    node *fin = euler(adj, n, 0);
    printf("Euler Path: ");
    node *temp = fin;
    while(temp!=NULL) {
        printf("%d ", temp->num);
        temp = temp->r;
    }
    printf("\n");
    
    // Clean up allocated memory
    free_adjacency_list(adj, n);
    free_path(fin);
    
    return 0;
}

Full Working Code

Putting it all together, the corrected code should work with your input file Assignment1.txt (which contains 2,3 3,1 1,2). When you enter 3 as the number of vertices, it will output the Euler path: 1 2 3 1.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 00:47:43