1.特点

  • 限制在一端进行插入与删除的线性表(俗称堆栈)
  • 允许进行操作的一段称栈顶,另一端固定,成为栈底
  • 栈中无元素成为空栈
  • 先进先出(FIFO)

2.顺序栈

2.1顺序栈结构体组成

  • 指针,指向栈顶;栈长度;栈顶数据下标
  • 采用此种方法可在创建栈时候指定栈容量
  • 结构图
  • 代码:
typedef struct
{
    datatype* data;//栈顶指针,指向保存数据的数组首地址
    int maxlen;
    int top;//栈顶数据下标
}seqstack;

2.2创建栈

  • 按照上述结构体定义,应该先申请一个12字节内存用于保存指向栈的地址指针,栈容量,栈顶数据下标;再申请指定大小的数组,用于保存数据
  • 初始化栈顶数据下标为-1,并指定栈大小
  • 代码:
seqstack* stack_create(int len)
{
    seqstack* s;
    if ((s = (seqstack*)malloc(sizeof(seqstack))) == NULL)
    {
        printf("malloc failed\n");
        return NULL;
    }
    if ((s->data = (datatype*)malloc(len * sizeof(datatype))) == NULL)
    {
        printf("malloc failed\n");
        return NULL;
    }
    s->maxlen = len;
    s->top = -1;
    return s;
}

2.3判断栈是否为空

  • 直接判断栈顶元素下标是否为-1即可,为-1代表空
  • 代码:
int is_stack_empty(seqstack* s)
{
    return(s->top == -1 ? 1 : 0);//空返回1,非空返回0
}

2.4判断栈是否为满

  • 当栈顶下标为2时候代表栈内有3个元素,故可据此判断栈是否为满
  • 代码:
int is_stack_full(seqstack* s)
{
    return(s->top == s->maxlen - 1 ? 1 : 0);//满返回1
}

2.5清空栈

  • 直接将栈顶数据下标设为-1,代表空栈
  • 代码:
void stack_clear(seqstack* s)
{
    s->top = -1;
}

2.6入栈

  • 即向数组内添加数据
  • 入栈前需判断栈是否满
  • 之后插入数据,移动栈顶下标指针即可
  • 代码:
int stack_push(seqstack* s, datatype value)
{
    if (is_stack_full(s))
    {
        printf("stack is full\n");
        return -1;
    }
    s->data[s->top + 1] = value;
    s->top++; 
    return 1;
}

2.7出栈

  • 出栈之前判断栈是否为空
  • 将栈顶指针-1
  • 取出数据
  • 代码:
datatype stack_pop(seqstack* s)
{
    if (is_stack_empty(s))
    {
        printf("stack is empty\n");
        return -1;
    }
    s->top--;
    return s->data[s->top + 1];/*返回出栈的元素*/
}

2.8取出栈顶数据

  • 代码:
datatype stack_top(seqstack* s)
{
    return (s->data[s->top]);
}

2.9销毁栈

  • 注意需要free两次,因为之前申请了两次
  • 将指针置空防止野指针
  • 代码:
void stack_free(seqstack* s)
{
    free(s->data);
    s->data = NULL;
    free(s);
    s = NULL;
}

3.链式栈

3.1链式栈组成

  • 其组成与单链表没什么区别
  • 如下:
typedef struct node
{
    datatype data;
    struct node* next;
}listnode;

3.2创建栈

  • 申请头节点即可
  • 代码:
listnode* linklist_stack_create()
{
    listnode* s;
    if ((s = (listnode*)malloc(sizeof(listnode))) == NULL)
    {
        printf("malloc failed\n");
        return NULL;
    }
    s->data = -1;
    s->next = NULL;
    return s;
}

3.3判断栈是否为空

  • 及直接判断其是否只含有头节点即可
  • 链式栈基于链表,其空间大小可随时创建,只要有存储空间就可以一直增加,故不用判断是否栈满
  • 代码:
int linklist_stack_is_empty(listnode* s)
{
    return(s->next == NULL ? 1 : 0);
}

3.4入栈

  • 类似与单链表的头插法
  • 代码:
int linklist_stack_push(listnode* s, datatype value)
{
    listnode *p;
    if ((p = (listnode*)malloc(sizeof(listnode))) == NULL)
    {
        printf("malloc failed\n");
        return -1;
    }
    p->data = value;
    p->next = s->next;
    s->next = p;
    return 0;
}

3.5出栈

  • 即删除头节点的下一个节点
  • 注意释放空间置空指针
  • 代码
datatype linklist_stack_pop(listnode* s)
{
    datatype ret;
    listnode *p;
    p = s->next;
    ret = p->data;
    s->next = p->next;
    free(p);
    p = NULL;
    return ret;
}

3.6取栈顶数据

  • 代码:
datatype linklist_stack_top(listnode* s)
{
    return (s->next->data);
}

3.7清空栈

  • 释放节点,头节点除外
  • 图解
  • 代码:
void linklist_stack_clear(listnode* s)
{
    listnode* p;
    p = s->next;
    while (p)
    {
        s->next = p->next;
        printf("%d is be delete\n", p->data);
        free(p);
        p = s->next;
    }
    p = NULL;
    puts("");
}

3.8释放栈

  • 释放节点,包含头节点
  • 图解
  • 代码:
void linklist_stack_free(listnode* s)
{
    listnode* p;
    p = s;
    while (p)
    {
        s = s->next;
        printf("%d is be delete\n", p->data);
        free(p);
        p = s;
    }
    puts("");
}

你可能感兴趣的:(栈)