数据结构 - 堆栈(通用数据结构)

堆栈的概念

堆栈是一种特殊的线性表,数据从栈顶进从栈顶出,遵循“先进后出”的原则。
堆栈的实现方式很多,以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;
}

结果:
结果
最后的最后,本人才疏学浅,此代码仅供参考交流,本人如有叙述错误,麻烦各位指正,有什么好的建议欢迎留言。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值