有一种爱不解释——我爱C语言!
/*
Name:纯C语言实现栈的相关操作
Copyright:欢迎共享此代码
Author:刁肥宅
Date: 04/08/18 21:55
Description:调试过程出行了一些失误,教训深刻!
*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdbool.h>
#include <time.h>
typedef struct Stack
{
int Data;
struct Stack *Next;
}LStack,*PStack;
typedef struct Position
{
struct Stack *PTop;
struct Stack *PBattom;
}LPosition,*PPosition;
bool InitiateStack(PPosition P);/*初始化栈*/
bool Push(PPosition P,int Value);/*压栈*/
bool Pop(PPosition P,int *Tmp);/*弹栈*/
void Top(PPosition P);/*访问栈顶元素*/
void Display(PPosition P);
void ClearStack(PPosition P);/*清空栈*/
bool EmptyStack(PPosition P);/*判断栈是否为空*/
int StackSize(PPosition P);/*求栈所含元素的多少*/
int main()
{
srand(time(NULL));
LPosition P,*LTmp = (LPosition *)malloc(sizeof(LPosition));/*LTmp的重要性在第65行代码处显现,似乎也没用*/
InitiateStack(&P);
int i,RandomValue,StackLength,*Tmp;/*n*/
int Operate,OperatingFrequency,OperatingKey,RandomPush = 0,RandomPop = 0;
LTmp = &P;/*在某次测试中(非当前测试函数体),P的地址赋值給LTmp,
导致第90行代码对栈的操作,会改变P的指向,
因此第104行代码总打印0*/
/*scanf("%d",&n);*/
StackLength = rand() % 10000 + 1;
OperatingFrequency = rand() % 100 + 1;
if( !InitiateStack(&P) )
{
printf("Initiate failed.\n");
exit(EXIT_FAILURE);
}
else
{
for(i = 0;i < StackLength;i ++)
{
RandomValue = rand() % 10000 + 1;
/*RandomValue = i + 1;*/
/*scanf("%d",&RandomValue);*/
Push(&P,RandomValue);
}
}
for(i = 0;i < OperatingFrequency;i ++)
{
Operate = rand() % 2 + 0;/*在0或者1之间选择*/
OperatingKey =rand() % 10000 + 1;/*随机压栈的数值*/
if(!Operate)/*0则弹栈*/
{
Pop(&P,&Tmp);
RandomPop ++;
}
else/*1则压栈*/
{
Push(&P,OperatingKey);
RandomPush ++;
}
}
Display(&P);
printf("\nRandomPush = %d,RandomPop = %d,variable 'StackLength' = %d\n",RandomPush,RandomPop,StackLength);
//ClearStack(&P);
//Pop(&P,&Tmp);
/*
if(Pop(&P,&Tmp))
printf("Y\n");
else
printf("N\n");
*/
/*在某次测试中(非当前测试函数体),正确显示栈所含元素个数*/
//printf("Stack size = %d\n",StackSize(LTmp));
/*
for(i = 0;i < n;i ++)
{
Top(&P);
if(Pop(&P,&Tmp))
continue;
else
break;
}
*/
/*在某次测试中(非当前测试函数体),总显示含0元素*/
printf("\nStack size = %d\n",StackSize(&P));
return 0;
}
bool InitiateStack(PPosition P)
{
P->PTop = (struct Stack*)malloc(sizeof(struct Stack));/*相当于申请一个新结点*/
if(!(P->PTop))/*申请不成功。养成良好的习惯,最好预先判断;万一哪天一个不小心内存泄漏了,哦嚯!*/
return false;
P->PBattom = P->PTop;/*栈底指向栈顶*/
/*
上面这句话我原来写作:
P->PTop = P->PBattom;
查了很长时间才发现问题是:
很丢人,没有初始化的指针就拿来赋值
*/
P->PTop->Next = NULL;/*栈顶指针置为空*/
return true;/*初始化成功*/
//return P;
}
bool Push(PPosition P,int value)
{
LStack *PNew = (LStack *)malloc(sizeof(LStack));/*相当于申请一个新结点*/
if(!PNew)/*申请不成功,压栈失败。养成良好的习惯,最好预先判断;万一哪天一个不小心内存泄漏了,哦嚯!*/
return false;
PNew->Data = value;/*数值赋給值域*/
PNew->Next = P->PTop;/*新结点的指针域指向栈顶*/
P->PTop = PNew;/*新结点成为新的栈顶*/
return true;/*压栈成功*/
}
bool Pop(PPosition P,int *Tmp)
{
LStack *PTmp = NULL;/*申请一个新结点,赋值为空*/
LPosition *LPTmp = (LPosition *)malloc(sizeof(LPosition));/*开辟一段空间給新结点*/
if(P->PTop->Next == NULL)/*栈顶指针为空说明栈为空*/
return false;/*弹栈失败*/
LPTmp = P;/*为什么创建这个临时结点,刁肥宅自己也不清楚,习惯吧*/
*Tmp = LPTmp->PTop->Data;
LPTmp->PTop = LPTmp->PTop->Next;/*栈顶的下一栈元素的指针指向栈顶*/
free(P);/*弹栈后释放空间*/
return true;/*弹栈成功*/
}
void Top(PPosition P)
{
LStack *PTmp = P->PTop;/*新建栈指针指向栈顶*/
printf("%d\n",PTmp->Data);/*打印栈顶元素 */
}
void Display(PPosition P)
{
LStack *Tmp = P->PTop;/*新建栈指针指向栈顶*/
int Line = 0;/*统计已结点个数*/
while(Tmp->Next != NULL)/*当栈顶指针不为空时*/
{
printf("%-6d",Tmp->Data);/*打印栈顶元素*/
Line ++;
if(Line % 10 == 0)
printf("\n");/*每行打印10个元素*/
Tmp = Tmp->Next;/*使栈顶的下一栈元素的指针指向栈顶*/
}
}
void ClearStack(PPosition P)
{
LPosition *PTmp = (LPosition *)malloc(sizeof(LPosition));/*创建临时位置指针*/
while(P->PTop->Next != NULL)/*当栈顶指针不为空时*/
{
PTmp = P;/*栈顶位置指针赋給临时位置指针*/
P->PTop = P->PTop->Next;/*使栈顶的下一栈元素的指针指向栈顶*/
free(P);/*释放当前栈顶元素的空间*/
}
}
bool EmptyStack(PPosition P)
{
return P->PTop->Next == NULL;/*当栈为空时,这句话为真,函数返回true;
当栈非空时,这句话为假,函数返回false*/
}
int StackSize(PPosition P)
{
LPosition *PTmp = (LPosition *)malloc(sizeof(LPosition));/*创建临时位置指针*/
//LStack *STmp = P->PTop;
PTmp = P;/*栈顶指针赋給临时位置指针*/
int ID = 0;/*初始化计数变量为0*/
while(PTmp->PTop->Next != NULL)/*当现在的栈顶元素指针不为空时,执行循环体*/
{
PTmp->PTop = PTmp->PTop->Next;/*使栈顶的下一栈元素的指针指向栈顶*/
ID ++;/*计数加一*/
}
return ID;/*返回栈元素的个数*/
}