【问题标题】:Insert into Nth position from the head of the stack从栈顶插入到第 N 个位置
【发布时间】:2015-07-12 06:55:41
【问题描述】:

我正在尝试解决我在使用 insertIntoS 函数时遇到的问题。我正在尝试从堆栈的头部向链表或堆栈中插入一个值。但是,我这样做并且它崩溃了。当我从最高点开始时它会起作用,我觉得这是因为头点指向 NULL。这是我的问题吗?我该如何解决这个问题才能从头部插入到第 n 个位置?

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct node{
    int data;
    struct node *next;
} Node;

typedef struct elem {
    int data;
    struct elem *next;
} Element;

Node *top = NULL;
Node *head = NULL;
Element *rear = NULL;
Element *front = NULL;
void pop();
void display();
void push (int num);
void dequeue();
void displayQ();
void insertIntoS(int data, int index);
void insertIntoQ(int data, int index);
void enqueue(int num);

int main(){
    int choice, num, index;

    while(1) {
        printf("\n 1 - Push");
        printf("\n 2 - Pop");
        printf("\n 3 - display stack");
        printf("\n 4 - Enqueue");
        printf("\n 5 - Dequeue ");
        printf("\n 6 - Show Queue ");
        printf("\n 7 - Insert Into Queue ");
        printf("\n 8 - Insert Into Stack ");
        printf("\n 9 - Exit ");
        printf("\n Please enter your choice");
        scanf("%d",&choice);
        switch (choice) {
            case 1:
                printf("Enter Data : ");
                scanf("%d", &num);
                push(num);
                break;
            case 2:
                pop();
                break;
            case 3:
                display();
                break;
            case 4:
                printf("Enter Data: ");
                scanf("%d", &num);
                enqueue(num);
                break;
            case 5:
                dequeue();
                break;
            case 6:
                displayQ();
                break;
            case 7:
                printf("Enter Data: ");
                scanf("%d", &num);
                printf("Enter the index: ");
                scanf("%d", &index);
                insertIntoQ(num, index);
                break;
            case 8:
                printf("Enter Data: ");
                scanf("%d", &num);
                printf("Enter the index: ");
                scanf("%d", &index);
                insertIntoS(num, index);
                break;
            case 9:
                exit(0);
            default:
                break;
        }
    }
}

void push (int num){
    Node *temp = (Node*) malloc(sizeof(Node));
    if(temp == NULL){
        printf("Stack OVERFLOW");
        return;
    }

    if(head == NULL) {
         temp->data = num;
        temp->next = NULL;
        head = temp;
        printf("Value of the head after push : %d \n", head->data);
    }
    temp->data = num;
    temp->next = top;
    top = temp;
}

void pop(){
    Node *temp;
    if(top == NULL){
        printf("You are trying to pop from a stack that is empty");
        return;
    }
    temp = top;
    top = top->next;
    free(temp);
}

void display(){
    Node *p;
    if(top == NULL){
        printf("Empty Stack");
        return;
    }
    printf("\n Stack : \n");
    p=top;
    while(p != NULL){
        printf("%d\n", p->data);
        p=p->next;
    }
}

void displayQ(){
    Element *p = front;
    if(p == NULL){
        printf("Empty stack\n");
        return;
    }else{
        printf("Queue: \n");
        while(p != NULL){
            printf("%d\n", p->data);
            p=p->next;
        }
    }
}

void dequeue(){
    Element *temp = front;
    if(front == NULL){
        printf("Queue is empty");
        return;
    }
    if(front == rear){
        front = rear = temp;
    }else{
        front = front->next;
    }
    free(temp);
}

void enqueue(int num){
    Element *temp = (Element*) malloc(sizeof(Element));
    if(temp == NULL){
        printf("Stack OVERFLOW");
        return;
    }
    temp->data = num;
    temp->next = NULL;
    if(front == NULL && rear == NULL){
        front = rear = temp;
    }
    rear->next = temp;
    rear = temp;
    printf("value of rear in enque: %d\n", rear->data);
}

void insertIntoQ(int data, int index){
    int i;
    Element *temp = (Element*) malloc(sizeof(Element));
    temp->data = data;
    temp->next = NULL;
    if(index == 1){
        temp->next = rear;
        rear = temp;
        return;
    }
    Element *temp1 = rear;
    for(i = 0; i<index;i++){
        temp1 = temp1->next;
    }
    temp->next = temp1->next;
    temp1->next = temp1;
}

void insertIntoS(int data, int index){
    int i;
    Node *temp1 = (Node*) malloc(sizeof(Node));
    temp1->data = data;
    temp1->next = NULL;
    if(index == 1){
        temp1->next = head;
        head = temp1;
        return;
    }

    printf("Value of head in insert %d\n", head->data);
    Node *temp2 = head;

    for(i = 0; i<index;i++){
        temp2 = temp2->next;
        printf("i count : %d\n", i);
    }
    temp1->next = temp2->next;
    temp2->next = temp1;
}

【问题讨论】:

  • 你能举一个导致程序崩溃的输入例子吗?
  • 我输入数据如下 1 1 1 2 1 3 1 4 1 5 8 9 3
  • 如果不清楚 ^^ Push 1 push 2 push 3 push 4 push 5 stack 看起来像 5 4 3 2 1 然后我在索引 3 处插入值 9
  • @Tyler Pierog 不清楚 head 和 top 是什么意思?它们有什么区别?
  • @Tyler Pierog 如果插入值的索引大于堆栈中的元素个数怎么办?

标签: c linked-list stack


【解决方案1】:

tophead 有什么区别? head 仅在您第一次推送后被分配,因此它始终指向堆栈的底部(最旧的节点); top 始终指向堆栈的顶部(最近的节点)。这似乎有点愚蠢。 insertIntoShead 开始并尝试向前移动 index 元素,但它已经在你的堆栈列表的末尾......你崩溃了。

您似乎创建了两个变量tophead,它们应该是相同的,而您在不同的地方只使用了一个或另一个,因此它们的用途和价值是不一致的。或者,您的想法对他们两个都不同,并且在使用他们两个时犯了一个错误。

在我看来,head 最有可能不存在,而 top 是您自始至终要使用的。


更详细的:

我假设您输入的顺序是“推 1、推 2、推 3、推 4、推 5、在索引 3 处插入 9”。

push() 中,您分配head 当且仅当它是NULL。因此,在 第一次 推送值 1 时,head 指向 Node{.data = 1}。 top 也指向同一个 Node{.data = 1}。

第二 向前推动 head != NULL,这样您就可以跳过 if 语句。 head 没有改变,它一直指向堆栈底部的 Node{.data = 1}!但是top总是指向最新的Node。

所以在你的推送结束时,你有:

5    4    3    2    1
^                   ^
top                 head

现在调用 insertIntoS(9, 3)。

您首先分配temp2 = head,所以现在temp2 指向堆栈底部的节点{.data = 1}。在 for 循环 (i = 0) 中,您分配 temp2 = temp2-&gt;next ... 所以现在 temp2NULL(因为 1 之后没有任何内容)。

在下一次 for 循环迭代 (i = 1) 中,您尝试访问 temp2-&gt;next,但 temp2NULL...您尝试取消引用空指针并崩溃。

insertIntoS 应该从堆栈开头的 5 开始(即top),对吗?这个head 变量似乎有点不靠谱。

【讨论】:

  • 我之前是从栈顶插入的。你所说的只是帮助强化了原因。感谢您的帮助,它真的解决了这个问题:)
【解决方案2】:

如果我理解正确,你必须编写两个容器:堆栈和队列。

事实上,您可以为两个容器使用相同的结构节点。但是在演示程序中,我对 Stack 的节点和 Queue 的节点使用了两种不同的结构,并将这些结构封装在结构 Stack 和结构 Queue 中。

以 Stack 的实现为模板,您需要自己编写 Queue 的实现。

这是演示程序。

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

struct Stack
{
    struct Node
    {
        int data;
        struct Node *next;
    } *top;
} stack;

void push ( int data )
{
    struct Node *tmp = malloc( sizeof( struct Node ) );
    tmp->data = data;
    tmp->next = stack.top;
    stack.top = tmp;

    printf( "Value on the top of the stack after push: %d \n", stack.top->data );
}    

void pop()
{
    if ( stack.top == NULL )
    {        
        printf( "You are trying to pop from a stack that is empty" );
    }
    else
    {
        struct Node *tmp = stack.top;
        stack.top = stack.top->next;
        printf( "The popped value from the stack: %d \n",  tmp->data );
        free( tmp );
    }
}    

_Bool is_stack_empty()
{
    return stack.top == NULL;
}

void clear_stack()
{
    while ( stack.top != NULL )
    {
        struct Node *tmp = stack.top;
        stack.top = stack.top->next;
        free( tmp );
    }
}

void insert_into_stack( int data, size_t index )
{
    struct Node *tmp = malloc( sizeof( struct Node ) );
    tmp->data = data;

    struct Node *after = NULL, *before = stack.top;
    size_t i = 0;

    for ( ; before != NULL && i < index; i++ )
    {
        after = before;
        before = before->next;
    } 

    tmp->next = before;
    if ( after == NULL )
    {
        stack.top = tmp;
    }
    else
    {
        after->next = tmp;
    }        

    printf( "Value %d is inserted at position %zu\n", tmp->data, i );
}    

void display_stack()
{
    if ( is_stack_empty() )
    {
        puts( "Stack is empty" );
    }
    else
    {
        printf( "\nStack:" );
        for ( struct Node *tmp = stack.top; tmp != NULL; tmp = tmp->next )
        {
            printf( " %d", tmp->data );
        }
        printf( "\n" );
    }
}

struct Queue
{
    struct Elem
    {
        int data;
        struct Elem *next;
    } *head, *tail;
} queue;

int main( void )
{
    int choice;

    do 
    {
        printf("\n  1 - Push");
        printf("\n  2 - Pop");
        printf("\n  3 - Insert Into Stack ");
        printf("\n  4 - Display Stack");
        printf("\n  5 - clear Stack");
        printf("\n  6 - Enqueue");
        printf("\n  7 - Dequeue ");
        printf("\n  8 - Insert Into Queue ");
        printf("\n  9 - Display Queue ");
        printf("\n 10 - Display Queue ");
        printf("\n 11 - Clear Queue ");
        printf("\n  0 - Exit ");
        printf("\n\n Please enter your choice: ");

        choice = 0;                  
        scanf( "%d", &choice );

        switch ( choice ) 
        {
            case 1:
            {
                int data = 0;
                printf("Enter Data : ");
                scanf( "%d", &data );
                push( data );
                break;
            }                
            case 2:
            {                
                pop();
                break;
            }                
            case 3:
            {
                int data = 0;
                printf("Enter Data : ");
                scanf( "%d", &data );
                size_t index = 0;
                printf( "Enter the index: " );
                scanf( "%zu", &index );
                insert_into_stack( data, index );
                break;
            }                
            case 4:
            {                
                display_stack();
                break;
            }                
            case 5:
            {                
                clear_stack();
                break;
            }                
            case 6: case 7: case 8: case 9: case 10:
            {                
                puts( "\nWrite it yourself\n" );
                break;
            }                
            default:
            {
                if ( choice != 0 ) 
                {                   
                    puts( "\nInvalid input. Try again.\n" );
                }
                else
                {
                    if ( !is_stack_empty() ) clear_stack();
                    //if ( !is_queue_empty() ) clear_queue();
                }                    
                break;
            }
        }                
    } while ( choice != 0 );                
}    

它可能有以下输出

  1 - Push
  2 - Pop
  3 - Insert Into Stack 
  4 - Display Stack
  5 - clear Stack
  6 - Enqueue
  7 - Dequeue 
  8 - Insert Into Queue 
  9 - Display Queue 
 10 - Display Queue 
 11 - Clear Queue 
  0 - Exit 

 Please enter your choice: 1
 Enter Data : 1
 Value on the top of the stack after push: 1 

  1 - Push
  2 - Pop
  3 - Insert Into Stack 
  4 - Display Stack
  5 - clear Stack
  6 - Enqueue
  7 - Dequeue 
  8 - Insert Into Queue 
  9 - Display Queue 
 10 - Display Queue 
 11 - Clear Queue 
  0 - Exit 

 Please enter your choice: 1
 Enter Data : 2
 Value on the top of the stack after push: 2 

  1 - Push
  2 - Pop
  3 - Insert Into Stack 
  4 - Display Stack
  5 - clear Stack
  6 - Enqueue
  7 - Dequeue 
  8 - Insert Into Queue 
  9 - Display Queue 
 10 - Display Queue 
 11 - Clear Queue 
  0 - Exit 

 Please enter your choice: 4
 Stack: 2 1

  1 - Push
  2 - Pop
  3 - Insert Into Stack 
  4 - Display Stack
  5 - clear Stack
  6 - Enqueue
  7 - Dequeue 
  8 - Insert Into Queue 
  9 - Display Queue 
 10 - Display Queue 
 11 - Clear Queue 
  0 - Exit 

 Please enter your choice: 3
 Enter Data : 3
 Enter the index: 1
 Value 3 is inserted at position 1

  1 - Push
  2 - Pop
  3 - Insert Into Stack 
  4 - Display Stack
  5 - clear Stack
  6 - Enqueue
  7 - Dequeue 
  8 - Insert Into Queue 
  9 - Display Queue 
 10 - Display Queue 
 11 - Clear Queue 
  0 - Exit 

 Please enter your choice: 4
 Stack: 2 3 1

  1 - Push
  2 - Pop
  3 - Insert Into Stack 
  4 - Display Stack
  5 - clear Stack
  6 - Enqueue
  7 - Dequeue 
  8 - Insert Into Queue 
  9 - Display Queue 
 10 - Display Queue 
 11 - Clear Queue 
  0 - Exit 

 Please enter your choice: 0

【讨论】:

    【解决方案3】:

    以下代码

    1) compiles cleanly, 
    2) contains several comments indicating probable problem areas
    3) checks for errors in system calls (I.E. malloc)
    

    发布的代码正在尝试创建/操作循环队列 并尝试创建/操作一个链表

    两个活动都存在逻辑错误,我不确定哪个活动包含您发现的问题。

    发布的代码(和此代码)在退出程序之前未能将所有 malloc 的内存传递给 free()。

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    typedef struct node{
        int data;
        struct node *next;
    } Node;
    
    typedef struct elem {
        int data;
        struct elem *next;
    } Element;
    
    Node *top = NULL;
    Node *head = NULL;
    
    Element *rear = NULL;
    Element *front = NULL;
    
    void pop( void );
    void display( void );
    void push (int num);
    void dequeue( void );
    void displayQ( void );
    void insertIntoS(int data, int index);
    void insertIntoQ(int data, int index);
    void enqueue(int num);
    
    int main()
    {
        int choice;
        int num;
        int index;
    
        while(1)
        {
            printf("\n 1 - Push");
            printf("\n 2 - Pop");
            printf("\n 3 - display stack");
            printf("\n 4 - Enqueue");
            printf("\n 5 - Dequeue ");
            printf("\n 6 - Show Queue ");
            printf("\n 7 - Insert Into Queue ");
            printf("\n 8 - Insert Into Stack ");
            printf("\n 9 - Exit ");
            printf("\n Please enter your choice");
    
            if( 1 != scanf("%d",&choice) )
            { // then scanf failed
                perror( "scanf for menu choice failed");
                exit( EXIT_FAILURE);
            }
    
            // immplied else, scanf successful
    
            switch (choice)
            {
                case 1:
                    printf("Enter Data : ");
                    scanf("%d", &num);
                    push(num);
                    break;
    
                case 2:
                    pop();
                    break;
    
                case 3:
                    display();
                    break;
    
                case 4:
                    printf("Enter Data: ");
                    scanf("%d", &num);
                    enqueue(num);
                    break;
    
                case 5:
                    dequeue();
                    break;
    
                case 6:
                    displayQ();
                    break;
    
                case 7:
                    printf("Enter Data: ");
                    scanf("%d", &num);
                    printf("Enter the index: ");
                    scanf("%d", &index);
                    insertIntoQ(num, index);
                    break;
    
                case 8:
                    printf("Enter Data: ");
                    scanf("%d", &num);
                    printf("Enter the index: ");
                    scanf("%d", &index);
                    insertIntoS(num, index);
                    break;
    
                case 9:
                    exit(0);
    
                default:
                    printf( "invalid value entered, valid values 0...9\n");
                    break;
            } // end switch
        } // end while
    } // end function: main
    
    
    void push (int num)
    {
        Node *temp = malloc(sizeof(Node));
        if(temp == NULL)
        {
            perror( "malloc for new stack node failed");
            exit( EXIT_FAILURE);
        }
    
        // implied else, malloc successful
    
        if(NULL == head )
        {
            temp->data = num;
            temp->next = NULL;
            head = temp;
            printf("Value of the head after push : %d \n", head->data);
        }
    
        else
        {
            temp->data = num;
            temp->next = top;
            top = temp;
        }
    } // end function: push
    
    
    void pop()
    {
        Node *temp;
        if(NULL == top)
        {
            printf("You are trying to pop from a stack that is empty");
            return;
        }
    
        temp = top;
        top = top->next;
        free(temp);
    } // end function: pop
    
    
    void display()
    {
        Node *p;
    
        if(top == NULL)
        {
            printf("Empty Stack");
            return;
        }
    
        printf("\n Stack : \n");
        p=top;
    
        while(p != NULL)
        {
            printf("%d\n", p->data);
            p=p->next;
        }
    } // end function: display
    
    
    void displayQ()
    {
        Element *p = front;
    
        if(p == NULL)
        {
            printf("Empty stack\n");
            return;
        }
    
        else
        {
            printf("Queue: \n");
    
            while(p != NULL){
                printf("%d\n", p->data);
                p=p->next;
            }
        }
    } // end function: displayQ
    
    
    void dequeue()
    {
        Element *temp = front;
    
        if(NULL == front)
        {
            printf("Queue is empty");
            return;
        }
    
        // nonsence code block
        if(front == rear)
        {
            front = rear = temp;
        }
    
        else
        {
            front = front->next;
        }
    
        free(temp);
    } // end funtion: dequeue
    
    
    void enqueue(int num)
    {
        Element *temp = malloc(sizeof(Element));
        if(NULL == temp )
        {
            perror( "malloc for new element failed");
            exit( EXIT_FAILURE);
        }
    
        // implied else, malloc successful
    
        temp->data = num;
        temp->next = NULL;
    
        if(front == NULL && rear == NULL){
            front = rear = temp;
        }
    
        else
        {
        rear->next = temp;
        rear = temp;  // probably incorrect
        }
    
        printf("value of rear in enque: %d\n", rear->data);
    } // end function: enqaueue
    
    
    void insertIntoQ(int data, int index)
    {
        int i;
        Element *temp = malloc(sizeof(Element));
        if( NULL == temp)
        { // then malloc failed
            perror( "malloc for new Element failed");
            exit( EXIT_FAILURE );
        }
    
        // implied else, malloc successful
    
        temp->data = data;
        temp->next = NULL;
    
        // probably incorrect
        if(index == 1){
            temp->next = rear;
            rear = temp;
            return;
        }
    
        Element *temp1 = rear;
        for(i = 0; i<index;i++)
        {
            temp1 = temp1->next;
        }
    
        temp->next = temp1->next;
        temp1->next = temp1; // probably should be: templ->next = temp;
    }
    
    void insertIntoS(int data, int index)
    {
        int i;
        Node *temp1 = malloc(sizeof(Node));
        if( NULL == temp1)
        { // then malloc failed
            perror( "malloc for new Node failed");
            exit( EXIT_FAILURE);
        }
    
        // implied else, malloc successful
    
        temp1->data = data;
        temp1->next = NULL;
    
        // probably incorrect as loses all other nodes
        if(index == 1)
        {
            temp1->next = head;
            head = temp1;
            return;
        }
    
        printf("Value of head in insert %d\n", head->data);
        Node *temp2 = head;
    
        for(i = 0; i<index;i++)
        {
            temp2 = temp2->next;
            printf("i count : %d\n", i);
        }
    
        // following 2 lines probably incorrect
        temp1->next = temp2->next;
        temp2->next = temp1;
    } // end function: insertIntoS
    

    【讨论】:

    • 强烈建议使用调试器来单步调试您的代码,这样您就可以准确地看到出了什么问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多