堆栈的概念
堆栈是一种特殊的线性表,数据从栈顶进从栈顶出,遵循“先进后出”的原则。
堆栈的实现方式很多,以C语言为例,堆栈可以是顺序堆栈(数据存储在连续的地址空间内),也可以是链式堆栈(地址不连续,通过链式指针链接),本文介绍的就C语言实现的通用数据结构型的顺序堆栈。
设计思路
参考数据结构 - 队列(顺序队列、通用数据类型)类似的思路,在堆栈初始化时候,完成堆栈空间的分配,并记录该空间的基地址,同样记录栈顶的位置,在出入栈时动态变化,采用以下的宏定义就可以实现访问数组式的访问到堆栈成员。
#define ARRAY_AT(arr, size, index) (*(((unsigned char *)arr)+(index)*(size)))
C语言代码
头文件
/*********************************************************************************************************
** Filename : stack.h
** Describe : This is a general-purpose C language stack module, with common data structure
** Version : V1.0.0
** Author : Lamdonn
** Date : 2022.07.23
********************************************************************************************************/
#ifndef __stack_H
#define __stack_H
typedef struct
{
void *arr; /* Address of data */
unsigned int item_size; /* Size of stack item */
unsigned int stack_len; /* Maximum length of stack */
unsigned int items_cnt; /* Count of items */
unsigned int top; /* Index at the end of the stack */
unsigned char state; /* Status of the stack */
}STACK;
unsigned char stack_init(STACK *stack, unsigned int item_size, unsigned int stack_len);
unsigned char stack_empty(STACK *stack);
unsigned char stack_full(STACK *stack);
unsigned int stack_cnt(STACK *stack);
unsigned char stack_push(STACK *stack, void *data);
unsigned char stack_pop(STACK *stack, void *data);
void stack_clean(STACK *stack);
void stack_free(STACK *stack);
#endif
STACK结构体当中,包含了存放队列成员空间的基地址(*arr),每个成员所占用的空间大小(item_size),栈深(stack_len),堆栈成员计数(items_cnt),栈顶索引。
源文件
/*********************************************************************************************************
** Filename : stack.c
** Describe : This is a general-purpose C language stack module, with common data structure
** Version : V1.0.0
** Author : Lamdonn
** Date : 2022.07.23
********************************************************************************************************/
#include "stack.h"
#include <string.h>
#include <stdlib.h>
#ifndef ARRAY_AT(arr, size, index)
#define ARRAY_AT(arr, size, index) (*(((unsigned char *)arr)+(index)*(size)))
#endif
/*********************************************************************************************************
** Name : stack_init
** Describe : Initialize stack
** Input : *stack: Address of the stack
item_size: Size of stack items
stack_len: Length of stack item
** Output : 1: Success
0: Fail
********************************************************************************************************/
unsigned char stack_init(STACK *stack, unsigned int item_size, unsigned int stack_len)
{
stack->arr = malloc(item_size * stack_len); /* Allocate space to stack */
if (stack->arr != NULL)
{
stack->item_size = item_size;
stack->stack_len = stack_len;
stack->top = 0;
stack->state = 0;
stack->items_cnt = 0;
}
else
{
return 0;
}
memset(stack->arr, 0, item_size * stack_len);
return 1;
}
/*********************************************************************************************************
** Name : stack_empty
** Describe : Judge whether the stack is empty
** Input : *stack: Address of the stack
** Output : 1: Empty
0: Not empty
********************************************************************************************************/
unsigned char stack_empty(STACK *stack)
{
if (stack->state == 0)
{
return 1;
}
else
{
return 0;
}
}
/*********************************************************************************************************
** Name : stack_full
** Describe : Check whether the stack is full
** Input : *stack: Address of the stack
** Output : 1: Full
0: Not full
********************************************************************************************************/
unsigned char stack_full(STACK *stack)
{
if (stack->top >= stack->stack_len - 1 && stack->state == 1)
{
return 1;
}
else
{
return 0;
}
}
/*********************************************************************************************************
** Name : stack_cnt
** Describe : Get current stack count
** Input : *stack: Address of the stack
** Output : The number of current items in the stack
********************************************************************************************************/
unsigned int stack_cnt(STACK *stack)
{
if (stack->state == 1)
{
return stack->top + 1;
}
else
{
return 0;
}
}
/*********************************************************************************************************
** Name : stack_push
** Describe : Queue items join the stack
** Input : *stack: Address of the stack
*data: Address of stack item data
** Output : 1: Success
0: Fail
********************************************************************************************************/
unsigned char stack_push(STACK *stack, void *data)
{
if (stack_full(stack))
{
return 0;
}
else
{
if (stack->state == 1)
{
stack->top++;
}
/* Copy this item to the stack */
memcpy(&ARRAY_AT(stack->arr, stack->item_size, stack->top), data, stack->item_size);
stack->items_cnt++;
stack->state = 1;
return 1;
}
}
/*********************************************************************************************************
** Name : stack_pop
** Describe : Queue items pop up the stack
** Input : *stack: Address of the stack
*data: Address of stack item data
** Output : 1: Success
0: Fail
********************************************************************************************************/
unsigned char stack_pop(STACK *stack, void *data)
{
if(stack_empty(stack))
{
return 0;
}
else
{
/* Extract data from pairs of columns */
memcpy(data, &ARRAY_AT(stack->arr, stack->item_size, stack->top), stack->item_size);
stack->items_cnt--;
if(stack->top == 0) /* When the top of the stack reaches the bottom, it means that the data is taken out */
{
stack->state = 0;
}
else
{
stack->top--;
}
return 1;
}
}
/*********************************************************************************************************
** Name : stack_clean
** Describe : Clean stack
** Input : *stack: Address of the stack
** Output : None
********************************************************************************************************/
void stack_clean(STACK *stack)
{
stack->top = 0;
stack->state = 0;
stack->items_cnt = 0;
}
/*********************************************************************************************************
** Name : stack_free
** Describe : Release stack
** Input : *stack: Address of the stack
** Output : None
********************************************************************************************************/
void stack_free(STACK *stack)
{
stack->top = 0;
stack->state = 0;
stack->items_cnt = 0;
stack->stack_len = 0;
stack->item_size = 0;
free(stack->arr);
stack->arr = NULL;
}
堆栈操作函数和队列差不多,包含初始化、入栈、出栈、清空、释放等操作。不对每行代码进行细述,直接看测试代码。
测试代码
#include <stdio.h>
#include "stack.h"
#include <string.h>
typedef struct
{
char name[10];
int height;
int age;
}STUDENT;
int main()
{
STACK stack;
STACK s_student;
int i = 0;
int data = 0;
STUDENT student;
int stack_count = 0;
stack_init(&stack, sizeof(int), 12);
stack_init(&s_student, sizeof(STUDENT), 6);
for (i = 0; i < stack.stack_len; i++)
{
data = i + 10;
stack_push(&stack, &data);
}
for (i = 0; i < s_student.stack_len; i++)
{
student.age = 18 + i;
student.height = 180 - i;
sprintf(student.name, "student%d", i+1);
stack_push(&s_student, &student);
}
stack_pop(&stack, &data);
stack_pop(&stack, &data);
stack_push(&stack, &data);
stack_push(&stack, &data);
printf("stack cnt: %d\r\n", stack.items_cnt);
stack_count = stack_cnt(&stack);
for (i = 0; i < stack_count; i++)
{
if (stack_pop(&stack, &data) == 1)
{
printf("%d\r\n", data);
}
}
stack_count = stack_cnt(&s_student);
for (i = 0; i < stack_count; i++)
{
if (stack_pop(&s_student, &student) == 1)
{
printf("name: %s, age = %d, height = %d\r\n", student.name, student.age, student.height);
}
}
getchar();
return 0;
}
结果:
最后的最后,本人才疏学浅,此代码仅供参考交流,本人如有叙述错误,麻烦各位指正,有什么好的建议欢迎留言。