• 编程练习(3)——栈


    今天用链表实现了栈的基本操作。其实,单链表本身就具有栈的特性,因而可以直接用不带头指针的单链表来模拟一个栈的操作。为了更好体现栈的特性和操作方便,将单链表封装到一个名为Stack的结构体中。其结构定义如下:

    typedef int DATA;
    typedef struct _snode SNode;
    
    /*定义栈节点类型*/
    typedef struct _snode
    {
        DATA data;
        SNode *next;
    }SNode;
    /*定义栈类型*/
    typedef struct _stack
    {
        SNode *top;
        int _size;//当前栈中节点数目
    }Stack,*LinkedStack;

    可以看出,在Stack中,除了用一个链表头指针存储栈顶元素外,还有一个int型的变量_size,用来存储栈中节点数目。这样可以方便获得栈的相关信息,也可以用for循环遍历等。当然,这也会带来一个问题。即,因为_size对程序员是公开的,而不像在OOP中可以定义为私有域,因而错误地直接修改_size的值会给相关操作带来麻烦。(C语言中有什么实现结构体域私有的方法么,请赐教^0^)。

    其实栈本身作为一种FIFO的数据结构,最重要的还是关注栈POP和PUSH吧。实际中的安全问题,需要根据具体情况作出判断。

    此外,对于指针的判空,栈元素的判空等,遵循的原则应该是各负其责,实现层次调用。代码中有些地方判断可能有些多余。

    上代码:

    #include <stdio.h>
    #include <stdlib.h>
    #ifndef STACK_H_INCLUDED
    #define STACK_H_INCLUDED
    
    typedef int DATA;
    typedef struct _snode SNode;
    
    /*定义栈节点类型*/
    typedef struct _snode
    {
        DATA data;
        SNode *next;
    }SNode;
    /*定义栈类型*/
    typedef struct _stack
    {
        SNode *top;
        int _size;//当前栈中节点数目
    }Stack,*LinkedStack;
    
    /*构造一个空栈,返回栈头指针*/
    Stack *InitStack();
    
    /*销毁一个栈*/
    void DestroyStack(Stack *ps);
    
    /*把栈置空*/
    void ClearStack(Stack *ps);
    
    /*判定是否为空栈*/
    int IsEmpty(Stack *ps);
    
    /*返回栈大小*/
    int GetSize(Stack *ps);
    
    /*返回栈顶元素*/
    DATA GetTop(Stack *ps);
    
    /*元素入栈,返回栈中元素数目*/
    int Push(Stack *ps,DATA d);
    
    /*元素出栈*/
    DATA Pop(Stack *ps);
    
    /*遍历栈并访问visit函数*/
    void StackTraverse(Stack *ps);
    
    #endif // STACK_H_INCLUDED

    Stack.c

    #include "Stack.h"
    
    /*构造一个空栈,返回栈头指针*/
    Stack *InitStack()
    {
        Stack *ps;
        ps=(Stack*)malloc(sizeof(Stack));
        if(ps==NULL)
        {
            perror("
    Stack:InitStack:分配内存失败!
    ");
            return;
        }
        else
        {
            ps->_size=0;
            ps->top=NULL;
            return ps;
        }
    }
    
    /*销毁一个栈*/
    void DestroyStack(Stack *ps)
    {
        if(ps==NULL)return;
        ClearStack(ps);
        free(ps);
    }
    
    /*把栈置空*/
    void ClearStack(Stack *ps)
    {
        while(IsEmpty(ps)==0)
        {
            Pop(ps);
        }
    }
    
    /*判定是否为空栈*/
    int IsEmpty(Stack *ps)
    {
        if(ps->top==NULL&&ps->_size==0)
        {
            return 1;
        }
        else if(ps->top==NULL&&ps->_size!=0)
        {
            ps->_size=0;
            return 1;
        }
        else if(ps->top!=NULL&&ps->_size==0)
        {
            ps->_size=CalcSize(ps->top);
            return 0;
        }
        return 0;
    }
    
    /*返回栈大小*/
    int GetSize(Stack *ps)
    {
        return ps->_size;
    }
    /*重新计算栈大小,内部函数*/
    int CalcSize(SNode *pn)
    {
        if(pn==NULL)return 0;
        SNode *p=pn;
        int i=0;
        while(p)
        {
            i++;
            p=p->next;
        }
    }
    /*返回栈顶元素*/
    DATA GetTop(Stack *ps)
    {
        if(ps==NULL) return;
        if(IsEmpty(ps)!=0) return;
        return ps->top->data;
    }
    
    /*元素入栈,返回栈中元素数目*/
    int Push(Stack *ps,DATA d)
    {
        if(ps==NULL)return;
        SNode *p;
        p=(SNode*)malloc(sizeof(SNode));
        if(p)
        {
            p->data=d;
            p->next=ps->top;
            ps->top=p;
            ps->_size++;
        }
        return ps->_size;
    }
    
    /*元素出栈*/
    DATA Pop(Stack *ps)
    {
        if(ps==NULL||IsEmpty(ps))
        {
            perror("
    Stack:Pop:栈空,返回!
    ");
            return;
        }
        SNode *p=ps->top;
        ps->top=p->next;
        ps->_size--;
        free(p);
    }
    void StackTraverse(Stack *ps)
    {
        if(ps==NULL)return;
        SNode *p=ps->top;
        while(p)
        {
            printf("%d	",p->data);
            p=p->next;
        }
    }

    主函数中有一个测试用函数:

    #include "Stack.h"
    
    void testStack();
    int main()
    {
        printf("
    ");
        testStack();
        return 0;
    }
    
    void testStack()
    {
        printf("
    ");
        Stack *ps=InitStack();
        int temp;
        int icount;
        if(ps==NULL)
        {
            perror("
    main:testStack:栈为空!
    ");
        }
        while(scanf("%d",&temp))
        {
            icount=Push(ps,temp);
        }
        printf("
    ");
        StackTraverse(ps);
        printf("
    ");
        while(IsEmpty(ps)==0)
        {
            printf("%d	",ps->top->data);
            Pop(ps);
        }
    
    }

    下面是一张调试结果,输入一个随意的非数字字符即可结束输入。

    QQ截图20151010123115

    欢迎交流!

  • 相关阅读:
    服务端主动关闭 time_wait
    告别Excel!别人家高大上的财务数据分析,这才是老板的最爱
    客户端主动关闭,timed_wait
    两千字揭密 MySQL 8.0.19 三大索引新功能:隐藏索引,降序索引,函数索引
    零基础入门深度学习(3)
    零基础入门深度学习(3)
    零基础入门深度学习(3)
    android 动画学习总结
    android 动画学习总结
    android 动画学习总结
  • 原文地址:https://www.cnblogs.com/myseasky/p/4866498.html
Copyright © 2020-2023  润新知