• 栈的定义及实现


    栈的定义
    栈是一种特殊的线性表
    栈仅能在线性表的一端进行操作
     栈顶(Top):允许操作的一端
     栈底(Bottom):不允许操作的一端
                  栈的性质

    栈的操作
      栈的一些常用操作
       创建栈
       销毁栈
       清空栈
       进栈
       出栈
       获取栈顶元素
       获取栈的大小
    栈的顺序存储实现
       顺序存储实现

    下面的顺序栈是不能支持结构体的!

    现在我们先来实现顺序栈,由于之前我们实现了顺序表,现在代码复用,用其来实现顺序栈。

    eg:

    SeqStack.h

    #ifndef _SEQSTACK_H_
    #define _SEQSTACK_H_
    
    typedef void SeqStack;
    typedef void * Stack_element;
    
    SeqStack* SeqStack_Create(int capacity);    
    
    void SeqStack_Destroy(SeqStack* stack);
    
    void SeqStack_Clear(SeqStack* stack);
    
    int SeqStack_Push(SeqStack* stack, Stack_element item);
    
    void* SeqStack_Pop(SeqStack* stack);
    
    void* SeqStack_Top(SeqStack* stack);
    
    int SeqStack_Size(SeqStack* stack);
    
    int SeqStack_Capacity(SeqStack* stack);
    
    #endif

    SeqStack.c

     1 #include "SeqStack.h"
     2 #include "SeqList.h"
     3 
     4 SeqStack* SeqStack_Create(int capacity)
     5 {
     6     return SeqList_Create(capacity);
     7 }
     8 
     9 void SeqStack_Destroy(SeqStack* stack)
    10 {
    11     SeqList_Destroy(stack);
    12 }
    13 
    14 void SeqStack_Clear(SeqStack* stack)
    15 {
    16     SeqList_Clear(stack);
    17 }
    18 
    19 int SeqStack_Push(SeqStack* stack, Stack_element item)
    20 {
    21     return SeqList_Insert(stack, item, SeqList_Length(stack));//压栈都是在尾部压入
    22 }
    23 
    24 void* SeqStack_Pop(SeqStack* stack)
    25 {
    26     return SeqList_Delete(stack, SeqList_Length(stack) - 1);//出栈是最后一个元素
    27 }
    28 
    29 void* SeqStack_Top(SeqStack* stack)
    30 {
    31     return SeqList_Get(stack, SeqList_Length(stack) - 1);//获取栈顶元素
    32 }
    33 
    34 int SeqStack_Size(SeqStack* stack)
    35 {
    36     return SeqList_Length(stack);
    37 }
    38 
    39 int SeqStack_Capacity(SeqStack* stack)
    40 {
    41     return SeqList_Capacity(stack);
    42 }

    SeqList.h (复用之前的代码)

     1 #ifndef _SEQLIST_H_
     2 #define _SEQLIST_H_
     3 
     4 typedef void SeqList;
     5 typedef void SeqListNode;
     6 
     7 SeqList* SeqList_Create(int capacity);
     8 
     9 void SeqList_Destroy(SeqList* list);
    10 
    11 void SeqList_Clear(SeqList* list);
    12 
    13 int SeqList_Length(SeqList* list);
    14 
    15 int SeqList_Capacity(SeqList* list);
    16 
    17 int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);
    18 
    19 SeqListNode* SeqList_Get(SeqList* list, int pos);
    20 
    21 SeqListNode* SeqList_Delete(SeqList* list, int pos);
    22 
    23 #endif
    View Code

    SeqList.c(复用之前的代码)

    #include <stdio.h>
    #include <malloc.h>
    #include "SeqList.h"
    
    typedef unsigned int TSeqListNode;
    
    typedef struct _tag_SeqList
    {
        int capacity;
        int length;
        TSeqListNode* node;
    } TSeqList;
    
    SeqList* SeqList_Create(int capacity) // O(1)
    {
        TSeqList* ret = NULL;
        
        if( capacity >= 0 )
        {
            ret = (TSeqList*)malloc(sizeof(TSeqList) + sizeof(TSeqListNode) * capacity);
        }
        
        if( ret != NULL )
        {
            ret->capacity = capacity;
            ret->length = 0;
            ret->node = (TSeqListNode*)(ret + 1);
        }
        
        return ret;
    }
    
    void SeqList_Destroy(SeqList* list) // O(1)
    {
        free(list);
    }
    
    void SeqList_Clear(SeqList* list) // O(1)
    {
        TSeqList* sList = (TSeqList*)list;
        
        if( sList != NULL )
        {
            sList->length = 0;
        }
    }
    
    int SeqList_Length(SeqList* list) // O(1)
    {
        TSeqList* sList = (TSeqList*)list;
        int ret = -1;
        
        if( sList != NULL )
        {
            ret = sList->length;
        }
        
        return ret;
    }
    
    int SeqList_Capacity(SeqList* list) // O(1)
    {
        TSeqList* sList = (TSeqList*)list;
        int ret = -1;
        
        if( sList != NULL )
        {
            ret = sList->capacity;
        }
        
        return ret;
    }
    
    int SeqList_Insert(SeqList* list, SeqListNode* node, int pos) // O(n) 
    {
        TSeqList* sList = (TSeqList*)list;
        int ret = (sList != NULL);
        int i = 0;
        
        ret = ret && (sList->length + 1 <= sList->capacity);
        ret = ret && (0 <= pos);
        
        if( ret )
        {
            if( pos >= sList->length )
            {
                pos = sList->length;
            }
            
            for(i=sList->length; i>pos; i--)
            {
                sList->node[i] = sList->node[i-1];
            }
            
            sList->node[i] = (TSeqListNode)node;
            
            sList->length++;
        }
        
        return ret;
    }
    
    SeqListNode* SeqList_Get(SeqList* list, int pos) // O(1) 
    {
        TSeqList* sList = (TSeqList*)list;
        SeqListNode* ret = NULL;
        
        if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )
        {
            ret = (SeqListNode*)(sList->node[pos]);
        }
        
        return ret;
    }
    
    SeqListNode* SeqList_Delete(SeqList* list, int pos) // O(n)
    {
        TSeqList* sList = (TSeqList*)list;
        SeqListNode* ret = SeqList_Get(list, pos);
        int i = 0;
        
        if( ret != NULL )
        {
            for(i=pos+1; i<sList->length; i++)
            {
                sList->node[i-1] = sList->node[i];
            }
            
            sList->length--;
        }
        
        return ret;
    }
    View Code

    main.c:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include "SeqStack.h"
     4 
     5 int main(int argc, char *argv[]) 
     6 {
     7     SeqStack* stack = SeqStack_Create(20);
     8     int a[10];
     9     int i = 0;
    10     
    11     for(i=0; i<10; i++)
    12     {
    13         a[i] = i;
    14         
    15         SeqStack_Push(stack, a + i);
    16     }
    17     
    18     printf("Top: %d
    ", *(int*)SeqStack_Top(stack));
    19     printf("Capacity: %d
    ", SeqStack_Capacity(stack));
    20     printf("Length: %d
    ", SeqStack_Size(stack));
    21     
    22     while( SeqStack_Size(stack) > 0 )
    23     {
    24         printf("Pop: %d
    ", *(int*)SeqStack_Pop(stack));
    25     }
    26     
    27     SeqStack_Destroy(stack);
    28     
    29     return 0;
    30 }

    运行结果:

     

    NOTE:由于线性表的实现利用了指针,而我们的编译器有可能是64bit也可能是32bit的,所以添加如下条件编译:

    Seqlist.c中增加:

    #include <stdio.h>
    #include <malloc.h>
    #include "SeqList.h"
    
    
    #define Compiler_64Bit
    //#define Compiler_32Bit
    #ifdef  Compiler_32Bit
        typedef unsigned int TSeqListNode;//为了存放一个指针强制类型转化后的值
    #endif
    
    #ifdef  Compiler_64Bit
        typedef long long TSeqListNode;//为了存放一个指针强制类型转化后的值
    #endif
    #if !defined(Compiler_32Bit) && !defined(Compiler_64Bit)
        #error "Compiler_32Bit or Compiler_64Bit not defined! see SeqList.c 6,7 line!
    "
    #endif

    栈的链式实现:

    链式栈是可以支持结构体的,但是要求和链式表一样需要包含特定的头,为了后续的例程复用,下面不使用结构体类型入栈操作。

    eg:

    LinkStack.h

    #ifndef _LINKSTACK_H_
    #define _LINKSTACK_H_
    
    //抽象数据类型
    typedef void LinkStack;
    
    //创建顺序栈
    LinkStack* LinkStack_Create();
    
    //销毁
    void LinkStack_Destroy(LinkStack* stack);
    
    //清除
    void LinkStack_Clear(LinkStack* stack);
    
    //压栈
    int LinkStack_Push(LinkStack* stack, void* item);
    
    //出栈,弹出
    void* LinkStack_Pop(LinkStack* stack);
    
    //栈顶
    void* LinkStack_Top(LinkStack* stack);
    
    //栈大小
    int LinkStack_Size(LinkStack* stack);
    
    #endif

    创建链式栈:

    这里复用了之前的顺序表的函数LinkList_Create();

     

    typedef  struct _tag_LinkListNode  LinkListNode;
    struct _tag_LinkListNode
    {
      LinkListNode* next;
    };

    typedef struct _tag_LinkList
    {
      LinkListNode header;
      int length;
    } TLinkList;

    这里使用LinkListNode header;head结构体里面包含了一个指向自身结构类型的指针,这就是我们的指针域,用来寻找下家的。
    链式表的源文件和头文件就不在贴出了,之前的随笔里面已经讲解和贴出了。

     链式栈的头文件:

    #ifndef _LINKSTACK_H_
    #define _LINKSTACK_H_
    
    typedef void LinkStack;
    
    LinkStack* LinkStack_Create();
    
    void LinkStack_Destroy(LinkStack* stack);
    
    void LinkStack_Clear(LinkStack* stack);
    
    int LinkStack_Push(LinkStack* stack, void* item);
    
    void* LinkStack_Pop(LinkStack* stack);
    
    void* LinkStack_Top(LinkStack* stack);
    
    int LinkStack_Size(LinkStack* stack);
    
    #endif

    源文件:

    #include <stdio.h>
    #include <malloc.h>
    #include "LinkStack.h"
    #include "LinkList.h"
    
    typedef struct _tag_LinkStackNode
    {
        LinkListNode header;
        void* item;
    } TLinkStackNode;
    
    LinkStack* LinkStack_Create()
    {
        return LinkList_Create();
    }
    
    void LinkStack_Destroy(LinkStack* stack)
    {
        LinkStack_Clear(stack);
        LinkList_Destroy(stack);
    }
    
    void LinkStack_Clear(LinkStack* stack)
    {
        while( LinkStack_Size(stack) > 0 )
        {
            LinkStack_Pop(stack);
        }
    }
    
    int LinkStack_Push(LinkStack* stack, void* item)
    {
        TLinkStackNode* node = (TLinkStackNode*)malloc(sizeof(TLinkStackNode));
        int ret = (node != NULL) && (item != NULL);
        
        if( ret )
        {
            node->item = item;
            
            ret  = LinkList_Insert(stack, (LinkListNode*)node, 0);
        }
        
        if( !ret )
        {
            free(node);
        }
        
        return ret;
    }
    
    void* LinkStack_Pop(LinkStack* stack)
    {
        TLinkStackNode* node = (TLinkStackNode*)LinkList_Delete(stack, 0);
        void* ret = NULL;
        
        if( node != NULL )
        {
            ret = node->item;
            
            free(node);
        }
        
        return ret;
    }
    
    void* LinkStack_Top(LinkStack* stack)
    {
        TLinkStackNode* node = (TLinkStackNode*)LinkList_Get(stack, 0);
        void* ret = NULL;
        
        if( node != NULL )
        {
            ret = node->item;
        }
        
        return ret;
    }
    
    int LinkStack_Size(LinkStack* stack)
    {
        return LinkList_Length(stack);
    }

    注意,上面的push操作时插入到链表首的,这样更快一些,不用循环到链表尾部。

    链式栈的清除不能直接调用链式表的清除,否则产生内存泄露,这里主要是为了之后的栈的例子,所以使用基本类型元素入栈,如果实现成可以支持结构体入栈的形式,直接调用链式表的清除函数即可,这个留给大家练手,可参考链式表的实现。

    链式栈的销毁是在调用了栈的清除函数之后再次调用链式表的销毁构成的,其他的复用没有什么变化。

    main函数:

    #include <stdio.h>
    #include <stdlib.h>
    #include "LinkStack.h"
    
    
    int main(int argc, char *argv[]) 
    {
        LinkStack* stack = LinkStack_Create();
        int a[10];
        int i = 0;
        
        for(i=0; i<10; i++)
        {
            a[i] = i;
            
            LinkStack_Push(stack, a + i);
        }
        
        printf("Top: %d
    ", *(int*)LinkStack_Top(stack));
        printf("Length: %d
    ", LinkStack_Size(stack));
        
        while( LinkStack_Size(stack) > 0 )
        {
            printf("Pop: %d
    ", *(int*)LinkStack_Pop(stack));
        }
        
        LinkStack_Destroy(stack);
        
        return 0;
    }

     程序的输出结果和顺序栈是一致的。

  • 相关阅读:
    DNS 查询长度
    WebSocket
    Overview of cookie persistence
    Linux Cluster
    keepalived + nginx 主主模式
    MIME 类型
    IaaS,PaaS,SaaS 的区别
    Linux下"负载均衡+高可用"集群的考虑点 以及 高可用方案说明(Keepalive/Heartbeat)
    交换机链路聚合与Linux的bond模式对照
    DHCP 中继
  • 原文地址:https://www.cnblogs.com/yangguang-it/p/8534518.html
Copyright © 2020-2023  润新知