插入栈顶的第N个位置

Insert into Nth position from the head of the stack

我正在尝试解决我的 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;
}

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

看起来你做了两个变量 tophead 本应该是同一个东西,但你在不同的地方只使用了一个或另一个,所以它们的用途和值不一致.或者,您的想法对它们来说都是不同的,并且在使用它们时犯了一个错误。

在我看来,head 最有可能不存在,而 top 是您打算在整个过程中使用的内容。


更详细:

我假设您正在输入序列 "push 1, push 2, push 3, push 4, push 5, insert 9 at index 3"。

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

second 上向前推,head != NULL 所以你跳过 if 语句。 head 没有改变,它仍然指向 Node{.data = 1} 处的堆栈底部!但是 top 总是指向最新的节点。

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

5    4    3    2    1
^                   ^
top                 head

现在调用 insertIntoS(9, 3)。

您从分配 temp2 = head 开始,所以现在 temp2 指向堆栈底部的 Node{.data = 1}。在 for 循环 (i = 0) 中,您分配 temp2 = temp2->next ... 所以现在 temp2NULL(因为 1 之后没有任何内容)。

在下一次 for 循环迭代 (i = 1) 中,您尝试访问 temp2->nexttemp2NULL...您尝试取消引用空指针并崩溃.

insertIntoS应该是从栈首的5开始(即top)吧?这个 head 变量似乎有点不稳定。

如果我没理解错你必须写两个容器:Stack 和 Queue。

事实上,您可以为两个容器使用相同的结构节点。但是在演示程序中,我为 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

下面的代码

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

发布的代码正在尝试 create/manipulate 循环队列 并尝试 create/manipulate 链表

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

发布的代码(和这段代码)未能在退出程序之前将所有 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