栈的介绍



栈和线性表很相似,不仅有顺序存储表示也有链式存储表示,而且其创建删除都一样。只是栈的操作方面有如下的特点:

(01) 栈中数据是按照"后进先出(LIFO, Last In First Out)"方式进出栈的。
(02) 向栈中添加/删除数据时,只能从栈顶进行操作。

栈通常包括的三种操作:pushpeekpop
push -- 向栈中添加元素。
peek -- 返回栈顶元素。
pop  -- 返回并删除栈顶元素的操作。


一:顺序存储表示

栈的示意图


1:栈的顺序存储结构表示:

#define STACKINITSIZE 100
#define STACKINCREMENT 10

typedef struct{
    SElemType *base;
    SElemType *top;
    int stacksize;
}SqStack;

这里需要注意的一点是:顺序存储只需要创建依次结构体,而这个结构体里面的指针不是指向该类型的结构体的(与链表不同),而是只想SElemType类型的数组的!创建的一个数组的信息,全在这个结构体里面表示。


2:栈的初始化

Stack stack_init(SqStack *S)
{
    S->base = (SElemType *)malloc(STACKINITSIZE * sizeof(SElemType));
    if(!(S->base))
        exit(-1);
    S->top = S->base;
    S->stacksize = STACKINITSIZE;
    return 1;
}

3:取得栈顶元素

由于栈顶指针top指向栈顶元素的下一个位置,因此取元素、插入元素以及删除元素都要留意数组索引的变化。同时还要判断栈是否为空,或者是否已满,然后再进行操作。

Status get_top(SqStack S,SElemType *e)
{
    if(S->top == S->base)
        return 0;
    *e = *(S->top - 1);
    return 1;
}

4:插入元素

Status push(SqStack *S,SElemType e)
{
    //判断元素空间十分充足
    if(S->top - S->base >= S->stacksize){
        S->base = (SElemType *)realloc(S->base,
                         (S->stacksize + STACKINCREMENT)*sizeof(SElemType));
        if(!(s->base))
            exit(-1);
        S->top = S->base + S->stacksize;
        S->stacksize += STACKINCREMENT;
    }
    *(S->top) = e;
    S->top++;
    return 1;
}

5:删除元素

Status pop(SqStack *S,SElemType *e)
{
    if(S->top == S->base)
        return 0;
    *e = *(--S->top);

    return 1;
}


评注:

栈、队列等其实就是一种工具,看你如何去用,如何去实现。这方式就有很多了。比如也可以用下面的方式来声明一个栈

#define MAXSIZE 200

struct seqstack

{

       Elemtype data[MAXSIZE];

       int top;

};

struct seqstack *s;  //定义一个指向顺序栈的指针


二:链式存储表示

当我们建立链表的时候,可以再表头插入结点也可以在表尾插入结点。那么在实现栈的时候,我们选择在表头插入结点,就能很好的实现我们想要的操作。但是,这里不需要头结点,只需要一个头指针就可以了。

1:单链表的结点

// 单向链表的“节点”
struct node {
    int val;
    struct node* next;
};

// 单向链表的“表头”
static struct node *phead=NULL;

2:创建结点(这里不用初始化,单链表时有表头,需要初始化)

// 创建节点,val为节点值
static struct node* create_node(int val) 
{
    struct node *pnode=NULL;
    pnode = (struct node*)malloc(sizeof(struct node));
    if (!pnode)
        return NULL;
    pnode->val = val;
    pnode->next = NULL;
    
    return pnode;
}

3:插入和删除的实现

// 将val插入到链表的表头位置
static struct node* push(int val) 
{
    struct node *pnode = NULL;
    
    pnode = create_node(val);
    pnode->next = phead;
    phead = pnode;
    
    return phead;
}

// 删除链表的表头
static int pop() 
{
    if (!phead)
    {
        printf("remove failed! link is empty!");
        return -1;
    }
    
    int ret;
    struct node *pnode;
    ret = phead->val;
    pnode = phead;
    phead = phead->next;
    free(pnode);

    return ret;
}


栈的链式存储实现代码

#include <stdio.h>
#include <malloc.h>

/**
 * C 语言: 单向链表实现的栈,只能存储int数据。
 *
 * @author skywang
 * @date 2013/11/07
 */

// 单向链表的“节点”
struct node {
    int val;
    struct node* next;
};

// 单向链表的“表头”
static struct node *phead=NULL;

// 创建节点,val为节点值
static struct node* create_node(int val) 
{
    struct node *pnode=NULL;
    pnode = (struct node*)malloc(sizeof(struct node));
    if (!pnode)
        return NULL;
    pnode->val = val;
    pnode->next = NULL;
    
    return pnode;
}

// 销毁单向链表
static int destroy_single_link() 
{
    struct node *pnode=NULL;

    while (phead != NULL) {
        pnode = phead;
        phead = phead->next;
        free(pnode);
    }
    return 0;
}

// 将val插入到链表的表头位置
static struct node* push(int val) 
{
    struct node *pnode = NULL;
    
    pnode = create_node(val);
    pnode->next = phead;
    phead = pnode;
    
    return phead;
}

// 删除链表的表头
static int pop() 
{
    if (!phead)
    {
        printf("remove failed! link is empty!");
        return -1;
    }
    
    int ret;
    struct node *pnode;
    ret = phead->val;
    pnode = phead;
    phead = phead->next;
    free(pnode);

    return ret;
}

// 返回链表的表头节点的值
static int peek() 
{
    if (!phead)
    {
        printf("peek failed! link is empty!");
        return -1;
    }

    return phead->val;
}

// 返回链表中节点的个数
static int size() 
{
    int count=0;
    struct node *pnode=phead;

    while (pnode != NULL) {
        pnode = pnode->next;
        count++;
    }
    return count;
}

// 链表是否为空
static int is_empty() 
{
    return phead==NULL;
}

// 打印“栈”
static void print_single_link()
{
    if (is_empty()) 
    {
        printf("stack is Empty\n");
        return 0;
    }

    printf("stack size()=%d\n", size());

    struct node *pnode=NULL;

    while (phead != NULL) {
        printf("%d\n", phead->val);
        pnode = phead;
        phead = phead->next;
        free(pnode);
    }
}

void main() 
{
    int tmp=0;

    // 将10, 20, 30 依次推入栈中
    push(10);
    push(20);
    push(30);

    //print_single_link();    // 打印栈

    // 将“栈顶元素”赋值给tmp,并删除“栈顶元素”
    tmp = pop();
    printf("tmp=%d\n", tmp);
    //print_single_link();    // 打印栈

    // 只将“栈顶”赋值给tmp,不删除该元素.
    tmp = peek();
    printf("tmp=%d\n", tmp);
    //print_single_link();    // 打印栈

    push(40);
    print_single_link();    // 打印栈

    // 销毁栈
    destroy_single_link();
}



三:双向链表实现的栈,能存储任意类型的数据

推荐看:栈的图文解析


另外推荐:栈的顺序存储和链式存储

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值