C语言基于链表的栈

学习数据结构与算法时实现的栈,参考书目《数据结构与算法分析 C语言描述》,以及在后面会分析我遇到的一个问题。

头文件:Stack.h

/*************************************
*功能:基于链表的栈,栈顶在表头
*作者:JK
*时间:2014--6-24
***************************************/

#ifndef _STACK_HEADER_H_
#define _STACK_HEADER_H_


typedef struct Node* pNode;
typedef pNode Stack;
typedef int ElementType;

struct Node
{
    ElementType element;
    pNode next;
};

Stack InitStack(void); // 初始化一个栈
void DeleteStack(Stack S);// 删除一个栈
void EmptyStack(Stack S); // 清空一个栈
int IsEmpty(Stack S);     // 判断是否是空栈,是返回true,否返回false
void Push(ElementType E, Stack S);// 将元素E压入栈顶
ElementType Pop(Stack S); //弹出栈顶的元素


#endif // _STACK_HEADER_H_


源文件:Stack.c

#include <stdlib.h>
#include <stddef.h>
#include <assert.h>
#include <stdio.h>
#include "Stack.h"


Stack InitStack(void)
{
    Stack S = (struct Node*)malloc(sizeof(struct Node));
    assert(S != NULL);

    S->next = NULL;
    return S;
}

void EmptyStack(Stack S)
{
    assert(S != NULL);

    while (S->next != NULL)
    {
        Pop(S);
    }
}

void DeleteStack(Stack S)
{
    assert(S != NULL);
    pNode p = S->next;
    pNode ptmp;
    while (p != NULL)
    {
        ptmp = p->next;
        free(p);
        p = ptmp;
    }
    free(S);
}

int IsEmpty(Stack S)
{
    assert(S != NULL);

    return S->next == NULL;
}

void Push(ElementType E, Stack S)
{
    assert(S != NULL);
    pNode p = (struct Node*)malloc(sizeof(struct Node));
    assert(p != NULL);
    p->element = E;
    p->next = S->next;
    S->next = p;
}

ElementType Pop(Stack S)
{
    assert(S != NULL);
    if (!IsEmpty(S))
    {
        ElementType e;
        pNode p = S->next;
        S->next = p->next;
        e = p->element;
        free(p);
        return e;
    }
    printf("This Stack is empty!!!\n");
    return 0;// 该返回值用来避免提示
}

主程序验证:main.c

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


int main()
{
    printf("Hello JK!\n");


    Stack myStack = InitStack();


    // 将0~9压入栈中,9在栈顶
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        Push(i, myStack);
    }


    // 弹出栈顶元素
    int a = Pop(myStack);
    printf("栈顶元素为:%d \n", a);

    DeleteStack(myStack);
    return 0;
}


下面分享并分析一下我写的过程中遇到的一个低级的错误。错误的根源在于初始化栈的函数,先看看这个函数:

void InitStack(Stack S)
{
    S = (struct Node*)malloc(sizeof(struct Node));
    assert(S != NULL);

    S->next = NULL;
}
用这个初始化函数初始化一个栈后,在运行Push函数等会操作这个栈的地方都会收到这个错误“Program received signal SIGSEGV, Segmentation fault.”,这个错误的原因一般是指针没初始化,后面在操作这个指针的时候就会出现错误。例如在主函数中:

int main()
{
    Stack myStack;
    InitStack(myStack);
}
myStack是一个指向节点的指针,且没初始化,即是一个野指针,通过InitStack(myStack)后,myStack还是一个野指针,因为我们直接将这个指针当作实参传给了InitStack函数,这样在调用后是不会改变该实参的,即没有初始化,其实这个道理只要学过C语言就知道的,但我为什么还是会犯这个低级错误呢,根本原因还是我理解的太肤浅了,我以为myStack是一个指针,传入指针是可以改变实参的值的,但其实不是这样的,如果本来实参就是一个指针的话,我们想改变该指针的值的话,就得传入指针的指针,好吧,到里就是这么简单,检查这个错误花了2个小时啊。一定要细致+努力啊。。。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值