刁肥宅手笔:纯C语言实现栈的相关操作

       有一种爱不解释——我爱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;/*返回栈元素的个数*/
}

猜你喜欢

转载自blog.csdn.net/u25th_engineer/article/details/81416093