版权声明:本文为博主原创文章,未经博主允许不得转载! https://blog.csdn.net/weixin_42839965/article/details/81747363
//pTop和pBottom直面是垃圾值,只有当两者同时指向一个没事实际含义的头结点时才造出一个空栈
void init(PSTACK pS)//将init(&S)中S的地址赋给pS
{
pS->pTop = (PNODE)malloc(sizeof(NODE));
if (NULL == pS->pTop)
{
printf("动态内存分配失败!\n");
exit(-1);
}
else//动态内存分配成功,将新的节点的地址存储在了pS->pTop
{
pS->pBottom = pS->pTop;
pS->pTop->Next = NULL;//pS->pBottom->Next=NULL;
//将新节点的指针域清空
}
}
压栈:
压栈都是压入当前栈顶的上方
/压栈
void push(PSTACK pS, int val)
{
PNODE pNew = (PNODE)malloc(sizeof(NODE));//导致新的节点
pNew->data = val; //把val的值赋给新节点的数据域
//新的节点的指针域要指向
pNew->Next = pS->pTop;//pS->pTop不能改成pBottom
pS->pTop = pNew;//新节点的指针域放到pS->pTop
return;
}
出栈:
直接将pS->pBotoom的值赋给pS->pTop会使得中间的节点无法找找到,造成内存泄漏,所以这个方法不行;
解决方法:先定义两个指针p和q,指针p指向栈顶,q指向p的下一个节点
//出栈,把pS所指向的栈出栈一次,并把出栈的元素存入pVal形参所指向的变量中,若出栈失败返回false,否则返回true
bool pop(PSTACK pS, int *pVal)
{
if (empty(pS))//pS本身存放的就是地址
{
return false;
}
else
{
PNODE r = pS->pTop;
*pVal = r->data;
pS->pTop=r->Next;
free(r);
r = NULL;
return true;
}
}
附 全部代码:
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct Node
{
int data;
struct Node *Next;
}NODE,*PNODE;
typedef struct Stack
{
PNODE pTop;//永远指向栈顶的位置
PNODE pBottom;//永远指向的是栈顶元素的下一个没有实际含义的元素
}STACK,*PSTACK;//PSTACK等价于struct STACK *
void init(PSTACK);//PSTACK是指针,改变实参STACK S的值
void push(PSTACK, int);
void traverse(PSTACK);
bool pop(PSTACK, int *);//出栈
void clear(PSTACK pS);//清空
int main(void)
{
STACK S;//STACK等价于struct Stack,变量S中含有ptop和pbottom两个成员
int val;
init(&S);//目的是造出空栈
//栈初始化,子函数调用,S无法改变变量STACK S的值,所以必须取地址,取地址用指针
//链表不会溢出,所以不需要返回值
push(&S,1);//压栈,只能从栈顶进行操作,无法指定插入的位置
push(&S,2);
push(&S,33);
push(&S,24);
push(&S,62);
push(&S,12);
traverse(&S);//遍历输出
printf("\n");
clear(&S);
traverse(&S);//遍历输出
printf("\n");
//出栈有可能会失败,所以需要返回值
if (pop(&S, &val))//将出栈的元素的值存储在val中
{
printf("出栈成功,出栈的元素是%d\n", val);
}
else
printf("出栈失败!\n");
traverse(&S);//遍历输出
return 0;
}
//初始化,造成空栈
//pTop和pBottom直面是垃圾值,只有当两者同时指向一个没事实际含义的头结点时才造出一个空栈
void init(PSTACK pS)//将init(&S)中S的地址赋给pS
{
pS->pTop = (PNODE)malloc(sizeof(NODE));
if (NULL == pS->pTop)
{
printf("动态内存分配失败!\n");
exit(-1);
}
else//动态内存分配成功,将新的节点的地址存储在了pS->pTop
{
pS->pBottom = pS->pTop;
pS->pTop->Next = NULL;//pS->pBottom->Next=NULL;
//将新节点的指针域清空
}
}
//压栈
void push(PSTACK pS, int val)
{
PNODE pNew = (PNODE)malloc(sizeof(NODE));//导致新的节点
pNew->data = val; //把val的值赋给新节点的数据域
//新的节点的指针域要指向
pNew->Next = pS->pTop;//pS->pTop不能改成pBottom
pS->pTop = pNew;//新节点的指针域放到pS->pTop
return;
}
//遍历输出,对栈遍历,输出栈顶和栈底,但是栈顶和栈底全部都在S里面,所以只需要;一个形参
//先定义一个指针P,永远指向栈顶元素,以次输出,直到P=pBottom结束
void traverse(PSTACK pS)
{
PNODE p = pS->pTop;
while (p!=pS->pBottom)
{
printf("%d ", p->data);
p = p->Next;
}
return;
}
bool empty(PSTACK pS)
{
if (pS->pBottom == pS->pTop)
return true;
else
return false;
}
//出栈,把pS所指向的栈出栈一次,并把出栈的元素存入pVal形参所指向的变量中,若出栈失败返回false,否则返回true
bool pop(PSTACK pS, int *pVal)
{
if (empty(pS))//pS本身存放的就是地址
{
return false;
}
else
{
PNODE r = pS->pTop;
*pVal = r->data;
pS->pTop=r->Next;
free(r);
r = NULL;
return true;
}
}
//
void clear(PSTACK pS)
{
if (empty(pS))
return;
else
{
PNODE p = pS->pTop;
PNODE q = NULL;
while (q != pS->pBottom)
{
q = p->Next;
free(p);
p = q;
}
pS->pTop = pS->pBottom;
}
}