一、栈(链式、数组)

说明

栈是最常见基础的一种数据结构,在算法的实现上,经常会使用到栈。本文主要目标是实现一个可以存储多种数据类型的栈,并提供常用的栈方法。本文采用三种方式来创建栈:定长数组、创建时指定长度数组、链式栈,提供的栈方法:

  • 创建栈
  • 栈空判断
  • 栈满判断
  • 入栈
  • 出栈
  • 获取栈顶元素
  • 栈销毁

1、定长数组栈

1.1、栈结构定义

栈结构 即是栈对象,其内包含数据对象数组、栈容量、栈长度、栈顶指针信息。为了存储不指定类型的数据,这里采用void*数组来存储,void*不指定指针的类型,实际上存储的是数据的地址,从而实现不指定数据类型。使用时,只需将出栈后的指针强转位需要的类型即可正常使用。这里需要自己注意存入与取出类型的区分,不要因为转型错误产生问题。

#define STACK_FIX_LEN 50
//栈对象(固定长度)
typedef struct ArrayStackFix{
	void* datas[STACK_FIX_LEN];	//数据内容,长度固定
	int size;		//最大容量
	int length;		//当前长度
	int top;		//栈顶指针
}ArrayStackFix;

1.2、创建栈

初始化栈对象,包括 分配栈对象空间、基础信息设置。

//创建栈,传入栈的接收数据空间地址(事先分配好), 传入栈最大容量
ArrayStackFix* createArrayStackFix(){
	ArrayStackFix *stack = (ArrayStackFix*)malloc(sizeof(ArrayStackFix));
	stack->length = 0;
	stack->size = STACK_FIX_LEN;
	stack->top = 0;
	return stack;
}

1.3、栈空判断

为空返回1,否则返回0

//栈空判断
int fixStackIsEmpty(ArrayStackFix *stack){
	if(stack->length == 0){
		return 1;
	}else{
		return 0;
	}
}

1.4、栈满判断

栈满则返回1,否则返回0

//栈满判断
int fixStackIsFull(ArrayStackFix *stack){
	if(stack->length == stack->size){
		return 1;
	}else{
		return 0;
	}
}

1.5、入栈

传入数据对象 和 栈对象,在栈未满时将数据入栈。

void fixStackPush(void* data,ArrayStackFix *stack){
	if(fixStackIsFull(stack) == 1){
		printf("入栈失败,栈已满!\n");
	}else{
		stack->datas[stack->top] = data;
		stack->top = stack->top+1;
		stack->length = stack->length+1;
	}
}

1.6、出栈

传入栈对象,将栈顶元素出栈。

//出栈
void* fixStackPop(ArrayStackFix *stack){
	if(fixStackIsEmpty(stack) == 1){
		printf("出栈失败,栈已空!\n");
		return NULL;
	}else{
		stack->top = stack->top-1;
		stack->length = stack->length-1;
		return (stack->datas[stack->top]);
	}
}

1.7、获取栈顶元素

传入栈对象,返回栈顶元素。这里不会移动栈顶指针

void* fixStackPeek(ArrayStackFix *stack){
	if(fixStackIsEmpty(stack) == 1){
		printf("出栈失败,栈已空!\n");
		return NULL;
	}else{
		return (stack->datas[stack->top -1]);
	}
}

1.8、销毁栈

释放栈空间

void fixStackDestroy(ArrayStackFix *stack){
	free(stack);
}

2、指定长度数组栈

2.1、栈结构定义

栈结构 即是栈对象,其内包含数据对象数组、栈容量、栈长度、栈顶指针信息。为了存储不指定类型的数据,这里采用void*数组来存储,void*不指定指针的类型,实际上存储的是数据的地址,从而实现不指定数据类型。使用时,只需将出栈后的指针强转位需要的类型即可正常使用。这里需要自己注意存入与取出类型的区分,不要因为转型错误产生问题。

 //栈对象(动态长度)
typedef struct ArrayStackDynamic{
	void** datas;	//数据内容,长度动态
	int size;		//最大容量
	int length;		//当前长度
	int top;		//栈顶
}ArrayStackDynamic;

2.2、创建栈

初始化栈对象(传入栈长度),包括分配栈对象空间、数据对象数组空间分配、基础信息设置。

//创建栈,传入栈的接收数据空间地址(事先分配好), 传入栈最大容量
ArrayStackDynamic* createArrayStackDynamic(int size){
	ArrayStackDynamic *stack = (ArrayStackDynamic*)malloc(sizeof(ArrayStackDynamic));
	stack->datas = (void**) malloc(sizeof(void*) * size);
	stack->length = 0;
	stack->size = size;
	stack->top = 0;
	return stack;
}

2.3、栈空判断

为空返回1,否则返回0

//栈空判断
int dynamicStackIsEmpty(ArrayStackDynamic *stack){
	if(stack->length == 0){
		return 1;
	}else{
		return 0;
	}
}

2.4、栈满判断

栈满则返回1,否则返回0

//栈满判断
int dynamicStackIsFull(ArrayStackDynamic *stack){
	if(stack->length == stack->size){
		return 1;
	}else{
		return 0;
	}
}

2.5、入栈

传入数据对象 和 栈对象,在栈未满时将数据入栈。

void dynamicStackPush(void* data,ArrayStackDynamic *stack){
	if(dynamicStackIsFull(stack) == 1){
		printf("入栈失败,栈已满!\n");
	}else{
		stack->datas[stack->top] = data;
		stack->top = stack->top+1;
		stack->length = stack->length+1;
	}
}

2.6、出栈

传入栈对象,将栈顶元素出栈。

//出栈
void* dynamicStackPop(ArrayStackDynamic *stack){
	if(dynamicStackIsEmpty(stack) == 1){
		printf("出栈失败,栈已空!\n");
		return NULL;
	}else{
		stack->top = stack->top-1;
		stack->length = stack->length-1;
		return (stack->datas[stack->top]);
	}
}

2.7、获取栈顶元素

传入栈对象,返回栈顶元素。这里不会移动栈顶指针

void* dynamicStackPeek(ArrayStackDynamic *stack){
	if(dynamicStackIsEmpty(stack) == 1){
		printf("出栈失败,栈已空!\n");
		return NULL;
	}else{
		return (stack->datas[stack->top -1]);
	}
}

2.8、销毁栈

释放栈空间

void dynamicStackDestroy(ArrayStackDynamic *stack){
	free(stack->datas);
	free(stack);
}

3、链式栈

3.1、栈结构定义

栈结构 包含栈节点(采用单向链表).

/**
 *	链式栈
 */
 //栈节点
 typedef struct StackNode{
	 void* data;
	 struct StackNode *next;//单向链表
 }StackNode;
//栈对象(固定长度)
typedef struct LinkedStack{
	StackNode *top;	//数据内容,长度固定
	int size;		//当前长度
}LinkedStack;

3.2、创建栈

初始化栈对象(传入栈长度),包括分配栈对象空间、基础信息设置。

//创建栈,传入栈的接收数据空间地址(事先分配好), 传入栈最大容量
LinkedStack* createLinkedStack(){
	LinkedStack *stack = (LinkedStack*)malloc(sizeof(LinkedStack));
	stack->size = 0;
	stack->top = NULL;
	return stack;
}

3.3、栈空判断

为空返回1,否则返回0

//栈空判断
int linkedStackIsEmpty(LinkedStack *stack){
	if(stack->size == 0){
		return 1;
	}else{
		return 0;
	}
}

3.4、栈满判断

链栈不会满

3.5、入栈

传入数据对象 和 栈对象,分配栈节点空间存储当前数据。

void linkedStackPush(void* val,LinkedStack *stack){
	StackNode *node = (StackNode*)malloc(sizeof(StackNode));
	node->data = val;
	node->next = stack->top;
	stack->top = node;
	stack->size = stack->size + 1;
}

3.6、出栈

传入栈对象,将栈顶元素出栈,释放栈顶元素所在栈节点空间。

//出栈
void* linkedStackPop(LinkedStack *stack){
	if(linkedStackIsEmpty(stack) == 1){
		printf("出栈失败,栈已空!\n");
		return NULL;
	}else{
		StackNode *node = stack->top;
		stack->top = node->next;
		stack->size = stack->size - 1;
		void* val = node->data;
		free(node);
		return val;
	}
}

3.7、获取栈顶元素

传入栈对象,返回栈顶元素。这里不会移动栈顶指针

void* linkedStackPeek(LinkedStack *stack){
	if(linkedStackIsEmpty(stack) == 1){
		printf("出栈失败,栈已空!\n");
		return NULL;
	}else{
		return stack->top->data;
	}
}

3.8、销毁栈

释放栈空间

void linkedStackDestroy(LinkedStack *stack){
	free(stack);
}

源码地址:https://download.csdn.net/download/Waiting_Love/89510372

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值