数据结构学习之栈篇

         栈(Stack)是限定只能在表的一端进行插入和删除操作的线性表。在表中,允许插入和删除的一端称作“栈顶(top)”,不允许插入和删除的另一端称作“栈底(bottom)”。      通常称往栈顶插入元素的操作为“入栈”,称删除栈顶元素的操作为“出栈”。因为后入栈的元素先于先入栈的元素出栈,故被称为是一种“后进先出”的结构,因此又称 LIFO 表(Last In First Out的缩写)。

           下面是顺序栈的基本架构的实现:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>  //使用bool必须包含此文件 
#define STACK_CAPACITY 5  //栈的容量大小

typedef struct tag_stack     //定义结构体类型,包含指针,顶部,长度
{
	char *pBuffer;
	int top;
	int length;
} Stack;

bool InitStack(Stack **pStack);  //栈的初始化,形参是指向结构体的指针的指针
void DestroyStack(Stack *pStack); //栈的销毁,形参是指向结构体的指针
bool StackEmpty(Stack *pStack);  //判断栈是否为空
bool StackFull(Stack *pStack);  //判断栈是否为满
void ClearStack(Stack *pStack);  //清空栈
int StackLength(Stack *pStack);//求栈中元素个数
bool Push(Stack *pStack,char *elem);//入栈,形参*elem为入栈元素
bool Pop(Stack *pStack,char *elem);  //出栈,
void StackTraverse(Stack *pStack,bool isFromButtom);    //遍历栈中所有元素 ,第二个形参为是否从底部遍历

bool InitStack(Stack **pStack)
{
	*pStack=(Stack*)malloc(sizeof(Stack));   //开辟一段内存,大小为一个结构体
	if(*pStack==NULL)   //如果返回的是空指针,开辟失败
	{
		return false;
	}
	(*pStack)->pBuffer=(char*)malloc(sizeof(char)*STACK_CAPACITY);//为结构体中的pBuffer开辟一片内存,大小为STACK_CAPACITY
	if(	(*pStack)->pBuffer ==NULL)   //判断内存开辟是否成功
	{
		return false;
	}
	ClearStack(*pStack); 
	return true;
} 


void DestroyStack(Stack *pStack)
{
	free(pStack->pBuffer);  //释放pBuffer所指向的内存
	pStack->pBuffer=NULL;    //修改野指针
	free(pStack);
	pStack=NULL;
	
}

void ClearStack(Stack *pStack)
{
		pStack->length=0;
		pStack->top=0;
}

bool StackEmpty(Stack *pStack)
{
	if(pStack->length==0)
	{
		return true;
	}
	return false;
}

bool StackFull(Stack *pStack)
{
	if(pStack->length == STACK_CAPACITY)
	{
		return true;
	}
	return false;
}

int StackLength(Stack *pStack)
{
	return pStack->length;
}

bool Push(Stack *pStack,char *elem)
{
	if(StackFull(pStack))//如果满栈
	{
		return false;
	}
	pStack->pBuffer[pStack->top++]=*elem;//*elem赋给栈顶元素,指针上移
	pStack->length++;//长度+1
	return true;
}

bool Pop(Stack *pStack,char *elem)
{
	if(StackEmpty(pStack))
	{
		return false;
	}
	
	*elem=pStack->pBuffer[--pStack->top];//赋值,指针下移
	pStack->length--;
    
    return true;
}

void StackTraverse(Stack *pStack,bool isFromButtom)
{
	if(isFromButtom)
	{
		int i;
		for(i=0;i<pStack->length;i++)
		{
			printf("%c",pStack->pBuffer[i]);
		}
	}
	else
		{
			int i;
			for(i=pStack->top-1;i>=0;i--)
			{
				printf("%c",pStack->pBuffer[i]);
			}
		}
}

int main(int argc, char *argv[])
 {
 	Stack  *myStack=NULL;
 	char ch1='A';
 	char ch2='C';
 	char ch3='E';
 	char ch4='F';
 	char ch5='G';
 	char ch=0;
	 if(InitStack(&myStack))//如果初始化成功
	 {
	 	if(StackEmpty(myStack))//如果栈为空
	 	{
	 		printf("当前栈为空\n");
	 	}
	 	
	 	Push(myStack,&ch1);//栈非空就压入5个元素
	 	Push(myStack,&ch2);
	 	Push(myStack,&ch3);
	 	Push(myStack,&ch4);
	 	Push(myStack,&ch5);
	 	printf("StackLength =  %d\n",StackLength(myStack));//打印栈长
	 	StackTraverse(myStack,true);//自底向上遍历
    if(StackFull(myStack))
		{
			printf("\n当前栈为满");
		} 
		Pop(myStack,&ch);  //弹出栈顶元素
	 	printf("\n%c\n",ch);
		printf("StackLength =  %d\n",StackLength(myStack));
	 	StackTraverse(myStack,true);
	 	DestroyStack(myStack);
	 } 
 	system("pause");
	return 0;
}

           下面是栈的应用实例,我利用上面的栈架构实现数制转换,输入十进制的数,然后转换为任意进制的数。

            数制转换公式:N=(N/d)*d+N%d

            举例说明这个原理(短除法):

              N             N div 8                N mod 8

            216           27                          0

            27              3                            3 

             3                0                           3


              由此可见,十进制的216对应8进制的330。

              下面是代码实现:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>  //使用bool必须包含此文件 
#define STACK_CAPACITY 15   //可处理的最大位数

typedef struct tag_stack
{
	char *pBuffer;
	int top;
	int length;
} Stack;

bool InitStack(Stack **pStack);
void DestroyStack(Stack *pStack);
bool StackEmpty(Stack *pStack);
bool StackFull(Stack *pStack);
void ClearStack(Stack *pStack);
int StackLength(Stack *pStack);
bool Push(Stack *pStack,char *elem);
bool Pop(Stack *pStack,char *elem);
void StackTraverse(Stack *pStack,bool isFromButtom);    //遍历栈中所有元素 

bool InitStack(Stack **pStack)
{
	*pStack=(Stack*)malloc(sizeof(Stack)); 
	if(*pStack==NULL)
	{
		return false;
	}
	(*pStack)->pBuffer=(char*)malloc(sizeof(char)*STACK_CAPACITY);
	if(	(*pStack)->pBuffer ==NULL)
	{
		return false;
	}
	ClearStack(*pStack);
	return true;
} 


void DestroyStack(Stack *pStack)
{
	free(pStack->pBuffer);
	pStack->pBuffer=NULL;
	free(pStack);
	pStack=NULL;
	
}

void ClearStack(Stack *pStack)
{
		pStack->length=0;
		pStack->top=0;
}

bool StackEmpty(Stack *pStack)
{
	if(pStack->length==0)
	{
		return true;
	}
	return false;
}

bool StackFull(Stack *pStack)
{
	if(pStack->length == STACK_CAPACITY)
	{
		return true;
	}
	return false;
}

int StackLength(Stack *pStack)
{
	return pStack->length;
}

bool Push(Stack *pStack,char *elem)
{
	if(StackFull(pStack))
	{
		return false;
	}
	pStack->pBuffer[pStack->top++]=*elem;
	pStack->length++;
	return true;
}

bool Pop(Stack *pStack,char *elem)
{
	if(StackEmpty(pStack))
	{
		return false;
	}
	*elem=pStack->pBuffer[--pStack->top];
	pStack->length--;
	return true;

}

void StackTraverse(Stack *pStack,bool isFromButtom)
{
	if(isFromButtom)
	{
		int i;
		for(i=0;i<pStack->length;i++)
		{
			printf("%c",pStack->pBuffer[i]);
		}
	}
	else
		{
			int i;
			for(i=pStack->top-1;i>=0;i--)
			{
				printf("%c",pStack->pBuffer[i]);
			}
		}
}

int main(int argc, char *argv[])
 {
 	Stack  *myStack=NULL;
    int num;
    int p;
    printf("请输入数字");
    scanf("\n%d",&num);
    printf("请输入进制");
    scanf("\n%d",&p);
    char str[]="0123456789ABCDEF";
	 if(InitStack(&myStack))
	 {
	 	
	 	while(num!=0)
	 	{
	 		Push(myStack,&(str[num%p]));
	 		num=num/p;
	 		
	 	}
	 	StackTraverse(myStack,false); 
	 
	 	DestroyStack(myStack);
	 } 
 	system("pause");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值