C语言实现栈的基本操作(超详细注释)

这篇文章更新了数据结构中栈的内容。在第一次写这个内容的时候,又出现了一大堆内存访问冲突。我本以为我对指针已经有深刻的了解了,经过这次我发现我还是有很多的不足。还是没有完全理解指针。所以对我的代码又进行了一次重构。后来就好了,现在我来分享一下我的代码。

本文中将会看到很多int型数据我也将它称为指针。因为我定义了一个动态内存分配的Elemtype* data,这些我称为指针的int型数据是相当于指针数组的下标。可以通过这个下标来找到我需要的指针。

头文件“栈.h”,存放了栈的定义和它相关的函数。

//蔚明
//栈.h

#ifndef 栈_H
#define 栈_H

#pragma warning(disable:4996)//这两段声明可以使scanf()在VS中正常使用
#pragma warning(disable:6031)


#include "stdio.h"
#include "stdlib.h"

#define OK 0
#define FAIL -1

typedef char Elemtype;

typedef struct Sqstack
{
    Elemtype* data;
    int top, stack_maxsize;
}Sqstack;


Sqstack Init_Stack(int maxsize);//初始化一个栈。

void Clear_Stack(Sqstack* S); //清空一个栈。

void Destroy_Stack(Sqstack* S); //销毁一个栈。

int Stack_Empty(Sqstack* S); //判断判断是否为空栈。

int Stack_Full(Sqstack* S); //判断判断是否为空栈。

int Stack_Length(Sqstack* S); //计算栈的长度。

int Get_Top_Stack(Sqstack* S, Elemtype* e); //仅读取不改变栈顶元素。

int Push_Stack(Sqstack* S, Elemtype e); //压入栈顶元素。

Elemtype Pop_Stack(Sqstack* S); //弹出栈顶元素。

int Stack_base_Traverse(Sqstack* S); //从栈底向栈顶对每个元素进行访问。

int Stack_top_Traverse(Sqstack* S); //从栈底向栈顶对每个元素进行访问。


#endif

下面是“栈.c”主要是栈的各种函数的定义

//蔚明
//栈.c

#include "栈.h"

Sqstack Init_Stack(int maxsize)//初始化一个栈。
{
	Sqstack S={NULL,0,0};
	S.stack_maxsize = maxsize;//确定最大容量
	if ((S.data = (Elemtype*)malloc(S.stack_maxsize * sizeof(Elemtype))) == NULL)//分配内存
	{
		puts("内存分配失败!!!");
		exit(1);
	}
	else
	{
		S.top =0;//栈顶指向栈底。
		return S;
	}
}

void Clear_Stack(Sqstack* S) //清空一个栈。
{
	for (int i = 0; Stack_Empty(S) != OK; i++)//在栈为空前弹出所有元素即可把栈置空
	{
		Pop_Stack(S);
	}
}

void Destroy_Stack(Sqstack* S) //销毁一个栈。
{
	free(S->data);//释放为栈分配的内存
}
  
int Stack_Empty(Sqstack* S) //判断判断是否为空栈。
{
	if (S->top == 0) return OK;//栈顶指针指向栈第时为空栈
	else return FAIL;
}

int Stack_Full(Sqstack* S) //判断判断是否为满。
{
	if (Stack_Length(S) == S->stack_maxsize) return OK;//当达到栈的最大容量时即栈满。
	else return FAIL;
}

int Stack_Length(Sqstack* S) //计算栈的长度。
{
	return S->top;//栈顶指针的数字即为栈的长度。
}

int Get_Top_Stack(Sqstack* S, Elemtype *e) //仅读取不改变栈顶元素。
{
	if (Stack_Empty(S) == OK) return FAIL;
	else
	{
		*e = S->data[S->top-1];//返回栈顶指针指向的元素,因为栈由0开始计数所以减一,原理和数组类似。
		return OK;
	}
}

int Push_Stack(Sqstack* S, Elemtype e) //压入栈顶元素。
{
	if (Stack_Full(S) == OK)
	{
		puts("栈满无法压入"); 
		return FAIL;
	}
	else 
	{
		S->data[S->top] = e;//把传进来的元素e赋给栈顶
		S->top++;//栈顶指针加一
		return OK;
	}
}

Elemtype Pop_Stack(Sqstack* S) //弹出栈顶元素。
{
	if(Stack_Empty(S)==OK) exit(1);
	Elemtype e = S->data[S->top-- - 1];//把栈顶元素赋给要返回的e后栈顶指针减一。
	return e;
}

int Stack_base_Traverse(Sqstack* S) //从栈底向栈顶对每个元素进行访问。
{
	if (Stack_Empty(S) == OK)//判断栈是否为空,此操作可避免内存冲突
	{
		puts("这个栈是空栈!");
		return FAIL;
	}
	else
	{
		int read = 0;//定义读取栈中元素的指针
		puts("从栈底向栈顶对每个元素进行访问。");
		for (read = 0; read < S->top; read++)//从栈底向栈顶对每个元素进行访问。
			printf("%c\t", S->data[read]);
		putchar('\n');
		return OK;
	}
}

int Stack_top_Traverse(Sqstack* S) //从栈底向栈顶对每个元素进行访问。
{
	if (Stack_Empty(S) == OK)//判断栈是否为空,此操作可避免内存冲突
	{
		puts("这个栈是空栈!");
		return FAIL;
	}
	else 
	{
		int read = 0;//定义读取栈中元素的指针
		puts("从栈顶向栈底对每个元素进行访问。");
		for (read = S->top - 1; read >= 0; read--)//从栈顶向栈底对每个元素进行访问。
			printf("%c\t", S->data[read]);
		putchar('\n');
		return OK;
	}
}

下面是"main.c",主要是验证“栈.c”中函数的使用是否正常

//蔚明
//main.c

#include "栈.h"
#include 

void main()
{
	/*验证Init_Stack(int maxsize),
	Push_Stack(Sqstack * S, Elemtype e),
	Stack_Full(Sqstack * S)*/
	puts("验证Init_Stack(int maxsize),\nPush_Stack(Sqstack * S, Elemtype e),\nStack_Full(Sqstack * S)\n\n");
	Sqstack S = Init_Stack(10);
	Elemtype e = '#',ch[15];
	puts("请输入要压入栈中的字符串\n");
	scanf("%s", ch);
	for (int i=0;i < strlen(ch); i++)
	{
		printf("正在压入第%d个元素\n", i);
		e = ch[i];
		if (Push_Stack(&S, e) != OK) puts("失败!!!");
	}

	/*验证Stack_base_Traverse(Sqstack * S),
	Stack_top_Traverse(Sqstack * S), 
	Stack_Length(Sqstack* S),
	Get_Top_Stack(Sqstack * S, Elemtype * e)*/
	puts("验证Stack_base_Traverse(Sqstack * S),\nStack_top_Traverse(Sqstack * S),\nStack_Length(Sqstack * S),\nGet_Top_Stack(Sqstack * S, Elemtype * e)\n");
	Get_Top_Stack(&S, &e);
	printf("栈顶元素为%c\n", e);
	printf("栈的长度为%d\n", Stack_Length(&S));
	Stack_base_Traverse(&S);
	Stack_top_Traverse(&S);

	//验证Pop_Stack(Sqstack* S)
	puts("验证Pop_Stack(Sqstack* S)\n\n");
	for (int i = 0; Stack_Empty(&S) != OK; i++)
	{
		printf("第%d个元素:%c\n", i + 1, Pop_Stack(&S));
	}

	//由于刚才弹出了所有元素,现重新为栈赋值。
	puts("由于刚才弹出了所有元素,现重新为栈赋值。\n");
	puts("请输入要压入栈中的字符串");
	scanf("%s", ch);
	for (int i = 0; i < strlen(ch); i++)
	{
		printf("正在压入第%d个元素\n", i);
		e = ch[i];
		if (Push_Stack(&S, e) != OK) puts("失败!!!");
	}
	//赋值后
	puts("赋值后\n");
	Stack_top_Traverse(&S);

	//验证Clear_Stack(Sqstack* S)
	puts("验证Clear_Stack(Sqstack* S)\n");
	Clear_Stack(&S);
	puts("执行“Clear_Stack(&S);”后:\n");
	Stack_top_Traverse(&S);

	//释放栈的内存,验证Destroy_Stack(Sqstack * S)
	puts("释放栈的内存,验证Destroy_Stack(Sqstack * S)");
	Destroy_Stack(&S);
	getchar();
}

运行结果如下:

C语言实现栈的基本操作(超详细注释)_第1张图片

C语言实现栈的基本操作(超详细注释)_第2张图片

C语言实现栈的基本操作(超详细注释)_第3张图片

经过验证都可以正常使用。

我学C语言大概半年,编写代码的手段可能比较稚嫩,如果写的比较垃圾,欢迎前辈指正。

你可能感兴趣的:(C语言实现数据结构中的算法,数据结构,c语言,经验分享)