作为素质练习,仅作参考,转载请标明出处链接
本文代码实现内容
- 链栈结构
- 同一个栈中能够入栈不同类型,不同大小的数据
- 说是泛型栈,实际应该是伪泛型吧。。。这段代码本来想用在表达式计算上的,后来觉得没必要,有点喧宾夺主了。
代码
- 头文件LStack.h
头文件中声明了各种数据类型,可以通过修改大小声明,实现各类数据的入栈。记得修改对应的释放函数避免内存泄露。
#ifndef _LSTACK_H_
#define _LSTACK_H_
/************************************************************
Copyright (C), 1988-1999
FileName: LStack.h 2021.01.02
Author:hzp Version :1.0
Description: //链表实现具有泛型特点的栈结构
Version: // v1.0
History: // 历史修改记录
<author> <time> <version > <desc>
***********************************************************/
#include "stdio.h"
#include "stdlib.h"
//定义bool类型
#ifndef BOOL
#define BOOL int
#define TRUE 1
#define FALSE 0
#endif
//定义栈元素的大小,可以根据个人需求求改大小
enum ElementSize {
sizeChar = 1, sizeDouble = 8
}ElementSize;
//链栈中的节点结构
typedef struct sNode* pNode; //栈结点指针
typedef void* stackElement;//栈结点元素
typedef int stackElementSize;//链栈中元素节点大小
//栈节点
typedef struct sNode {
stackElement element;
stackElementSize elementSize;
pNode next;
}sNode;
typedef struct linkStack {
pNode top; //栈顶
int count; //元素数量
}linkStack;
//初始化链栈
void initStack(linkStack *lStack);
//入栈
BOOL pushStack(linkStack *lStack , pNode pushNode);
//出栈
void popStack(linkStack *lStack, pNode popNode);
//查看栈顶元素(不出栈)
void readStack(linkStack *lStack, pNode popNode);
//释放栈
void freeStack(linkStack *lStack);
//释放栈节点
void freeNode(pNode node);
//设置节点数据
BOOL setNodeData(pNode node, stackElement data, stackElementSize size);
//打印节点数据
void printfStackNode(pNode node);
#endif
- 源文件LStack.c
#include"LStack.h"
#include <stdlib.h>
//函数定义
//初始化链栈
void initStack(linkStack *lStack)
{
lStack->top = NULL;
lStack->count = 0;
}
/*************************************************
@ Function: pushStack
@ Description:
入栈操作,头插法
@ Input:
lStack //栈指针
elemt //入栈元素指针
size //入栈元素大小
@ Output:
@ Return:
入栈成功/失败
@ Others:
*************************************************/
BOOL pushStack(linkStack *lStack, pNode pushNode)
{
stackElement Data = NULL;//栈节点数据元素
pNode Node = NULL;//栈节点
pNode temp = NULL;//临时节点
if (!pushNode||!pushNode->element)return FALSE;
Data = (stackElement)malloc(pushNode->elementSize);
Node = (pNode)malloc(sizeof(sNode));
if (!Data||!Node) //申请空间失败
{
if (Data)free(Data);
if (Node)free(Node);
return FALSE;
}
memcpy(Data, pushNode->element,pushNode->elementSize);//数据拷贝到自己节点空间
Node->element = Data;
Node->elementSize = pushNode->elementSize;
Node->next = NULL;
//头插法,插入节点
temp= lStack->top;
lStack->top = Node;
Node->next = temp;
lStack->count += 1;
return TRUE;
}
/*************************************************
@ Function: popStack
@ Description:
出栈操作
@ Input:
lStack //栈指针
@ Output:
popNode //将出栈的元素赋值到该指针上
@ Return:
@ Others:
popNode指针空间需要开辟,以保证达到空间需求
*************************************************/
void popStack(linkStack *lStack, pNode popNode)
{
pNode tempNode = NULL;//栈节点
if (lStack->count <= 0)return;//栈空
//赋值节点元素数据
memcpy(popNode->element, lStack->top->element, lStack->top->elementSize);
popNode->elementSize= lStack->top->elementSize;
//释放节点空间
tempNode = lStack->top;
lStack->top = lStack->top->next;
freeNode(tempNode);//
lStack->count -= 1;//计数
return ;
}
/*************************************************
@ Function: readStack
@ Description:
查看栈顶元素(不出栈)
@ Input:
lStack //栈指针
@ Output:
popNode //将栈顶的元素赋值到该指针上
@ Return:
@ Others:
popNode指针空间需要开辟,以保证达到空间需求
*************************************************/
void readStack(linkStack *lStack, pNode popNode)
{
pNode tempNode = NULL;//栈节点
if (lStack->count <= 0)return;//栈空
//赋值节点元素数据
memcpy(popNode->element, lStack->top->element, lStack->top->elementSize);
popNode->elementSize = lStack->top->elementSize;
return;
}
//销毁栈
void freeStack(linkStack *lStack)
{
pNode temp = NULL;
temp = lStack->top;
while (temp&&temp->element)//栈内还有元素
{
lStack->top = lStack->top->next;
freeNode(temp);
lStack->count--;//测试用
temp = lStack->top;
}
lStack->count = 0;
}
//释放栈节点
void freeNode(pNode node)
{
free(node->element);
free(node);
node = NULL;
}
/*************************************************
@ Function: setNodeData
@ Description:
设置节点数据
@ Input:
node //栈结点指针
data //要设置的数据指针
size //数据大小
@ Output:
@ Return:
@ Others:
*************************************************/
BOOL setNodeData(pNode node, stackElement data, stackElementSize size)
{
if (!node ||!node->element || !data)return FALSE;
memcpy(node->element, data, size);
node->elementSize = size;
return TRUE;
}
//打印节点数据
void printfStackNode(pNode node)
{
char data1 = 0;
double data2=0;
if (!node || !node->element)return;
switch (node->elementSize)
{
case sizeChar:
{
memcpy(&data1, node->element, node->elementSize);
printf("data=%c,size=%d\n",data1,node->elementSize);
break;
}
case sizeDouble:
{
memcpy(&data2, node->element, node->elementSize);
printf("data=%.2lf,size=%d\n",data2, node->elementSize);
break;
}
}
}
简单测试一下栈,测试代码如下
linkStack Lstack; //栈变量
sNode node; //栈节点
double data1 = 0; //数据类型1
char data2 = '('; //数据类型2
initStack(&Lstack); //初始化栈
node.element = (stackElement)malloc(sizeDouble); //为节点开辟数据空间
node.next = NULL;
for (int i = 0; i < 5; i++)
{
data1 += 1;
setNodeData(&node, &data1, sizeDouble); //设置节点数据为double
pushStack(&Lstack, &node); //入栈
setNodeData(&node, &data2, sizeChar); //设置节点数据为char
pushStack(&Lstack, &node); //入栈
}//入栈顺序:1(2(3(4(5(
//查看、出栈并打印
printf("栈内元素数量=%d\n", Lstack.count);
while (Lstack.count > 0)
{
readStack(&Lstack, &node); //查看栈顶元素
printfStackNode(&node);//打印节点数据
popStack(&Lstack, &node); //出栈
}
free(node.element);
入栈顺序:1(2(3(4(5( 出栈结果如下,测试通过)