c-泛型栈的实现

作为素质练习,仅作参考,转载请标明出处链接

本文代码实现内容

  1. 链栈结构
  2. 同一个栈中能够入栈不同类型,不同大小的数据
  3. 说是泛型栈,实际应该是伪泛型吧。。。这段代码本来想用在表达式计算上的,后来觉得没必要,有点喧宾夺主了。

代码

  1. 头文件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

  1. 源文件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( 出栈结果如下,测试通过)
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值