栈的定义及实现

栈的定义
栈是一种特殊的线性表
栈仅能在线性表的一端进行操作
 栈顶(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\n", *(int*)SeqStack_Top(stack));
19     printf("Capacity: %d\n", SeqStack_Capacity(stack));
20     printf("Length: %d\n", SeqStack_Size(stack));
21     
22     while( SeqStack_Size(stack) > 0 )
23     {
24         printf("Pop: %d\n", *(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!\r\n"
#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\n", *(int*)LinkStack_Top(stack));
    printf("Length: %d\n", LinkStack_Size(stack));
    
    while( LinkStack_Size(stack) > 0 )
    {
        printf("Pop: %d\n", *(int*)LinkStack_Pop(stack));
    }
    
    LinkStack_Destroy(stack);
    
    return 0;
}

 

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

posted @ 2018-03-09 16:15  Crystal_Guang  阅读(3278)  评论(0编辑  收藏  举报