棧——線性表變異體
棧是一種插入和刪除都在同一端的線性表。這個同一端叫棧頂
。棧的插入和刪除都在同一端,所以最後插入的數據肯定會最先會被取出,這種邏輯結構叫先進後出
——LIFO(Last in first out)
。插入操作叫入棧
,刪除操作叫出棧
。
實現棧可以使用數組或鏈表來實現
使用鏈表實現代碼
- 數據結構
typedef struct _data_node
{
int data;
struct _data_node *prev;
}data_node_t;
typedef struct _link_stack
{
data_node_t *top; //指向棧頂
int stack_size; //棧的大小
int stack_count; //入棧數據計數
}link_stack_t;
- 數據節點的初始化
static data_node_t *data_node_init(int data)
{
data_node_t *d = (data_node_t *)malloc(sizeof(data_node_t));
if(!d)
return NULL;
d->data = data;
d->prev = NULL;
return d;
}
- 數據節點解初始化
static int data_node_deinit(data_node_t *data_node)
{
if(!data_node)
return -1;
data_node->data = 0;
data_node->prev = NULL;
free(data_node);
return 0;
}
- 判斷棧是否爲空
static int is_stack_empty(link_stack_t *s)
{
return (s->stack_count == 0);
}
- 判斷棧是否滿
static int is_stack_full(link_stack_t *s)
{
return ( s->stack_count >= s->stack_size );
}
- 初始化棧
int link_stack_init(link_stack_t *s, int stack_size)
{
if(!s)
return -1;
s->top = NULL;
s->stack_count = 0;
s->stack_size = stack_size;
}
- 解初始化棧
int link_stack_deinit(link_stack_t *s)
{
if(!s)
return -1;
if(is_stack_empty(s))
{
s->top = NULL;
s->stack_count = 0;
s->stack_size = 0;
}
else
{
data_node_t *node = s->top;
for(int i = 0; ( (i < s->stack_count) && !node); i++, node = node->prev)
{
data_node_deinit(node);
}
}
return 0;
}
- 入棧
int link_stack_push(link_stack_t *s, int val)
{
if(!s)
return -1;
data_node_t *d = data_node_init(val);
if(!d)
return -1;
if(is_stack_full(s))
return -1;
if(is_stack_empty(s))
{
s->top = d;
s->stack_count++;
return 0;
}
else
{
d->prev = s->top;
s->top = d;
s->stack_count++;
return 0;
}
}
- 出棧
int link_stack_pop(link_stack_t *s, int *val)
{
data_node_t *node;
if(!s)
return -1;
if(is_stack_empty(s))
return -1;
node = s->top; //保存當前要取出的節點
*val = s->top->data; //取出棧中的數據
s->top = node->prev; //棧頂指向下面一個節點
s->stack_count--; //
data_node_deinit(node);
return 0;
}
測試
- 代碼
/************************************************************************
* @file: xxx.c
* @author: guangjieMVP
* @github: https://github.com/guangjieMVP
* @version: v1.0.0
* @date: 2020-xx-xx
* @brief:
**************************************************************************/
#include "stdio.h"
#include "link_stack.h"
#include "string.h"
#define LINK_STACK_SIZE 6
link_stack_t link_stack;
int main(int argc, char **argv)
{
int data;
link_stack_init(&link_stack, LINK_STACK_SIZE);
if(link_stack_push(&link_stack, 1) == -1)
{
printf("push failed\r\n");
}
else
{
printf("push success\r\n");
}
if(link_stack_push(&link_stack, 2) == -1)
{
printf("push failed\r\n");
}
else
{
printf("push success\r\n");
}
if(link_stack_push(&link_stack, 3) == -1)
{
printf("push failed\r\n");
}
else
{
printf("push success\r\n");
}
if(link_stack_push(&link_stack, 4) == -1)
{
printf("push failed\r\n");
}
else
{
printf("push success\r\n");
}
if(link_stack_push(&link_stack, 5) == -1)
{
printf("push failed\r\n");
}
else
{
printf("push success\r\n");
}
if(link_stack_push(&link_stack, 6) == -1)
{
printf("push failed\r\n");
}
else
{
printf("push success\r\n");
}
if(link_stack_push(&link_stack, 7) == -1)
{
printf("push failed\r\n");
}
else
{
printf("push success\r\n");
}
link_stack_pop(&link_stack, &data);
printf("%d\r\n",data);
link_stack_pop(&link_stack, &data);
printf("%d\r\n",data);
link_stack_pop(&link_stack, &data);
printf("%d\r\n",data);
link_stack_pop(&link_stack, &data);
printf("%d\r\n",data);
link_stack_pop(&link_stack, &data);
printf("%d\r\n",data);
link_stack_pop(&link_stack, &data);
printf("%d\r\n",data);
if( link_stack_pop(&link_stack, &data) == (-1) )
{
printf("stack is empty\r\n");
}
else
{
printf("%d\r\n",data);
}
return 0;
}
- 測試結果
可以看到先進
的數據經過出棧的操作後出
。