#ifndef _KN_LINKSTACK_H_
#define _KN_LINKSTACK_H_
//使用链表的链式存储 模拟栈的链式存储
typedef void LinkStack;
//创建栈 相当于创建一个线性表
LinkStack* LinkStack_Create();
//销毁栈 相当于 销毁一个线性表
void LinkStack_Destroy(LinkStack* stack);
//清空一个栈 相当于 清空一个线性表
void LinkStack_Clear(LinkStack* stack);
//向栈中添加元素 相当于 向线性表的头部插入元素
int LinkStack_Push(LinkStack* stack, void* item);
//从栈中弹出元素 相当于从线性表的头部删除元素
void* LinkStack_Pop(LinkStack* stack);
//获取栈顶元素 相当于获取线性表的0号位置
void* LinkStack_Top(LinkStack* stack);
//栈的大小
int LinkStack_Size(LinkStack* stack);
#endif //_MY_LINKSTACK_H_
/*
栈的链式存储结构,简称链栈
栈顶放在链表的头部进行插入和删除操作
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "knLinklist.h"
#include "knLinkstack.h"
#include "knDebug.h"
typedef struct _tag_LinkStackNode{ //相当于链表的业务节点
LinkListNode node; //必须在首位
void *item; //栈的业务节点(是指针)
}TLinkStackNode;
//创建栈 相当于创建一个线性表
LinkStack* LinkStack_Create()
{
return LinkList_Create();
}
//销毁栈 相当于 销毁一个线性表(!!)
void LinkStack_Destroy(LinkStack* stack)
{
LinkStack_Clear(stack); //先弹出栈的所有元素
LinkList_Destroy(stack);
return ;
}
//清空一个栈 相当于 清空一个线性表(!!)
void LinkStack_Clear(LinkStack* stack)
{
/*
清空栈的时候涉及到栈的生命周期管理,所有入栈的节点
都是malloc,若要清空栈,把栈中元素弹出,并且释放内存
*/
if (stack == NULL){
return;
}
while (LinkStack_Size(stack) > 0){
LinkStack_Pop(stack);//在这个函数中释放节点的内存
}
return;
}
//向栈中添加元素 相当于 向线性表的头部插入元素
//void * item栈的业务节点--》转化为 链表的业务节点
int LinkStack_Push(LinkStack* stack, void* item)
{
TLinkStackNode *tmp = NULL;
int ret = 0;
tmp = (TLinkStackNode*)malloc(sizeof(TLinkStackNode));
if (tmp == NULL){
return -1;
}
memset(tmp, 0, sizeof(TLinkStackNode));
tmp->item = item; //业务数据
//向链表的头部插入元素
ret = LinkList_Insert(stack, (LinkListNode*)tmp, 0);
if (ret != 0){
DEBUG("func LinkList_Insert() err:%d \n", ret);
if (tmp != NULL){
free(tmp);
}
return ret;
}
return ret;
}
//从栈中弹出元素 相当于从线性表的头部删除元素
void* LinkStack_Pop(LinkStack* stack)
{
void *item = NULL;//栈的业务节点
TLinkStackNode *tmp = NULL;
tmp = (TLinkStackNode *)LinkList_Delete(stack, 0);
if (tmp == NULL){
return NULL;
}
//从链表节点中取出业务节点
item = tmp->item;
free(tmp);//因为LinkList_Insert的时候分配了内存,所以LinkList_Delete需要释放内存
return item;
}
//获取栈顶元素 相当于获取线性表的0号位置
void* LinkStack_Top(LinkStack* stack)
{
TLinkStackNode *tmp = NULL;
tmp = (TLinkStackNode *)LinkList_Get(stack, 0);
if (tmp == NULL){
return NULL;
}
return tmp->item;
}
//栈的大小
int LinkStack_Size(LinkStack* stack)
{
return LinkList_Length(stack);
}
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "knLinkstack.h"
#if 0
/*
用线性表的链式存储来模拟栈的线性存储:
难点1:
如果在链表的尾部删除一个元素,因为链表是单向的,需要从头节点
开始遍历,找到尾部元素再删除。
而在链表得头部不需要遍历,因此在链表的头节点进行元素的增删
难点2:
push函数栈业务节点转化为链表业务节点
*/
void test()
{
int a[10], i;
LinkStack *stack = NULL;
stack = LinkStack_Create();
if (stack == NULL){
return;
}
for (i = 0; i < 10; i++){
a[i] = i + 1;
printf("------push: %d\n", a[i]);
LinkStack_Push(stack, &a[i]);
}
printf("栈的大小:%d\n", LinkStack_Size(stack));
printf("栈顶top:%d\n", *((int*)LinkStack_Top(stack)));
//删除栈中的所有元素
while (LinkStack_Size(stack) > 0){
printf("------pop: %d\n", *((int*)LinkStack_Pop(stack)));
}
LinkStack_Destroy(stack);
}
#endif
int main()
{
test();
printf("\n");
system("pause");
return 0;
}