【问题标题】:Stack implimentation using Linkedlist in C在 C 中使用链表实现堆栈
【发布时间】:2020-01-16 09:30:06
【问题描述】:

我用 C 语言编写了一个代码来使用 LinkedList 算法实现堆栈。这是代码............

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
struct listNode {
int data;
struct listNode *next;
};
struct stack{
struct stack *top;
};
struct stack *createstk(){
    struct stack *stk;
    stk=malloc(sizeof(struct stack));
    stk->top=NULL;
    return stk;
}
void push(struct stack *stk,int data){
    struct listNode *temp;
    temp=malloc(sizeof(struct listNode));
    if(!temp){
        printf("heap overflow");
        return;
    }
    temp->data=data;
    temp->next=stk->top;
    stk->top=temp;
}
int pop(struct stack *stk){
    if(isEmpty(stk))
        return INT_MIN;
    int data;
    struct listNode *temp;
    temp= stk->top;
    stk->top=stk->top->next;
    data=temp->data;
    delete(temp);
    return data;
}
int peek(struct stack *stk){
    if(isEmpty(stk))
        return INT_MIN;
    return stk->top->data;
}
int isEmpty(struct stack *stk){
    return stk->top==NULL;
}
void deleteStack(struct stack *stk){
    struct listNode *temp,*p;
    p=stk->top;
    while(p){
        temp=p->next;
        p=p->next;
        free(temp);
    }
    free(stk);
}
int main(){
    int i=0;
    struct stack *stk=createstk();
    for(i=0;i<=10;i++)
        push(stk,i);
    printf("Top Element is %d",peek(stk));
    for(i=0;i<=10;i++){
        printf("popped element is %d",pop(stk));
    }
    if(isEmpty(stk))
        printf("stack is empty");
    else
        printf("stack is not empty");
    deleteStack(stk);
    return 0;
}

[警告]来自不兼容指针类型的赋值。 正如您在图片中看到的那样。我是编码世界的新手,第一次遇到这个错误。这就是为什么我不知道该怎么办。请告诉我...

【问题讨论】:

  • struct listNode *temp; 创建 temp 作为指向 listNode 的指针(temp-&gt;next 相同)。您尝试temp-&gt;next=stk-&gt;top;,它尝试分配stk-&gt;top(类型指针指向struct stack)。您不能将指向 struct stack 的指针分配给指向 listNode 的指针。 (您始终有类似的错误)
  • temp->next 指向与 stk->top 不同的类型

标签: c data-structures linked-list stack singly-linked-list


【解决方案1】:

类型 stack 中的字段 top 类型错误。改变

struct stack {
    struct stack *top;
};

struct stack {
    struct listNode *top;
};

【讨论】:

  • 这是一个开始,但这并不能解决问题。
  • @DavidC.Rankin 但它回答了这个问题。
  • 是的,这是一个真实的陈述。但一般来说,当有人在一个类型问题上苦苦挣扎时,在存在许多其他问题的情况下单独提供一个类型问题的答案,只会将他转移到下一个错误,然后他又被卡住了。你的答案很好,我在我发布的答案中给予了你的信任,但我总是尝试扮演老师的角色,帮助学生解决剩下的问题。这两种方法都没有错。
  • @DavidC.Rankin 同意,尽管学习奋斗也很好。
【解决方案2】:

您有大量错误以stack-&gt;top 的错误类型开头,正如August Karlstrom 正确指出的那样,您的成员top 的类型必须是struct listNode *top;,例如

struct stack {
    struct listNode *top;
};

在更正之后,您必须对函数重新排序或提供 isEmpty()deleteStack() 的函数原型。在它们第一次使用之前将它们移到你的代码中将解决问题,例如

struct stack *createstk()
{
    struct stack *stk;
    stk = malloc (sizeof (struct stack));
    stk->top = NULL;
    return stk;
}

int isEmpty (struct stack *stk)
{
    return stk->top == NULL;
}

void deleteStack (struct stack *stk)
{
    struct listNode *temp, *p;
    p = stk->top;
    while (p) {
        temp = p->next;
        p = p->next;
        free (temp);
    }
    free (stk);
}
...

接下来,这是 C,而不是 C++,没有 delete 函数来释放内存,所以在 pop() 中,您必须调用 free (temp); 而不是 delete (temp);

最后,提供间距以使您的代码可读。结合上述内容,您可以执行以下操作:

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

struct listNode {
    int data;
    struct listNode *next;
};

struct stack {
    struct listNode *top;
};

struct stack *createstk()
{
    struct stack *stk;
    stk = malloc (sizeof (struct stack));
    stk->top = NULL;
    return stk;
}

int isEmpty (struct stack *stk)
{
    return stk->top == NULL;
}

void deleteStack (struct stack *stk)
{
    struct listNode *temp, *p;
    p = stk->top;
    while (p) {
        temp = p->next;
        p = p->next;
        free (temp);
    }
    free (stk);
}

void push (struct stack *stk, int data){

    struct listNode *temp;

    temp = malloc (sizeof *temp);
    if (!temp) {
        perror ("push()-malloc-temp");
        return;
    }

    temp->data = data;
    temp->next = stk->top;
    stk->top = temp;
}

int pop(struct stack *stk){

    int data;
    struct listNode *temp;

    if (isEmpty(stk))
        return INT_MIN;

    temp = stk->top;
    data = temp->data;
    stk->top = stk->top->next;

    free (temp);

    return data;
}
int peek(struct stack *stk){
    if(isEmpty(stk))
        return INT_MIN;
    return stk->top->data;
}

int main (void) {
    int i=0;
    struct stack *stk=createstk();

    for (i = 0; i <= 10; i++)
        push(stk,i);

    printf("Top Element is %d\n",peek(stk));

    for (i = 0; i <= 10; i++)
        printf ("  popped element is %d\n",pop(stk));

    if (isEmpty(stk))
        printf ("stack is empty\n");
    else
        printf ("stack is not empty\n");

    deleteStack(stk);

    return 0;
}

使用/输出示例

$ ./bin/stack_ll
Top Element is 10
  popped element is 10
  popped element is 9
  popped element is 8
  popped element is 7
  popped element is 6
  popped element is 5
  popped element is 4
  popped element is 3
  popped element is 2
  popped element is 1
  popped element is 0
stack is empty

内存使用/错误检查

在您编写的任何动态分配内存的代码中,对于分配的任何内存块,您都有 2 个职责:(1)始终保留指向起始地址的指针内存块,因此,(2) 当不再需要它时可以释放

您必须使用内存错误检查程序来确保您不会尝试访问内存或写入超出/超出分配块的边界,尝试读取或基于未初始化的值进行条件跳转,最后,以确认您释放了已分配的所有内存。

对于 Linux,valgrind 是正常的选择。每个平台都有类似的内存检查器。它们都易于使用,只需通过它运行您的程序即可。

$ valgrind ./bin/stack_ll
==25935== Memcheck, a memory error detector
==25935== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==25935== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==25935== Command: ./bin/stack_ll
==25935==
Top Element is 10
  popped element is 10
  popped element is 9
  popped element is 8
  popped element is 7
  popped element is 6
  popped element is 5
  popped element is 4
  popped element is 3
  popped element is 2
  popped element is 1
  popped element is 0
stack is empty
==25935==
==25935== HEAP SUMMARY:
==25935==     in use at exit: 0 bytes in 0 blocks
==25935==   total heap usage: 12 allocs, 12 frees, 184 bytes allocated
==25935==
==25935== All heap blocks were freed -- no leaks are possible
==25935==
==25935== For counts of detected and suppressed errors, rerun with: -v
==25935== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

始终确认您已释放已分配的所有内存并且没有内存错误。

如果您还有其他问题,请告诉我。

【讨论】:

  • 感谢您的宝贵时间。我曾向我的大学教授询问过这个问题,但他不理我。所以,我在社区发布了这个问题。是工作。我对指针有些困惑。那么,你能帮我解决这个问题,或者建议我一些在线资源或任何你能做的事情吗?我需要澄清我的概念,因为我没有从我的先生那里得到任何帮助。再次感谢。
  • @B.Sarkar 阅读Obtaining address of pointer in C with and without ampersand, what's the difference? 的答案,如果您仍有疑问,请告诉我。指针只是一个普通变量,它保存其他东西的地址作为它的值。换句话说,一个指针指向存储其他东西的内存地址。
猜你喜欢
  • 2012-05-24
  • 2019-03-04
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
  • 1970-01-01
  • 2021-10-30
相关资源
最近更新 更多