数据结构(四)——栈

栈是一种限定性线性表,遵循后进先出(LIFO)原则,分为顺序栈和链式栈。顺序栈可能出现上溢和下溢现象,而链式栈在编程中更常见。栈在程序设计中主要应用于表达式求值、递归调用等场景。本文介绍了栈的结构体定义、入栈、出栈等相关操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

栈,即stack,同样是线性表。只是它在设计时,运算规则做了限制。是限定性的线性表结构。

栈,只能在固定的一端插入和取出(取出,也就意味着删除了)。通常,能插入删除的那一端,叫做栈顶,top;不能插入删除的,称为栈底,bottom。插入栈,称为入栈。删除,称为出栈/退栈。当栈中没有元素时,称为空栈。
学习过单片机的应该对栈有了解,毕竟是有一个实实在在的物理容器的概念。出入栈的原则,是先进后出,last in first out(LIFO),因此,栈又被称为,后进先出表。

栈,同样分为顺序栈和链式栈。
如果是顺序栈的话,可能在运算时出现“溢出”。溢出分两种,上溢和下溢。若系统分配的作为栈的储存区满了,还有元素进栈,则是上溢。如果栈里已经没有元素了,还要执行出栈,则是下溢。上溢是一种错误现象,需要分配更大的空间,下溢则常用于作为控制转移的条件或者程序结束的标志。

但是,之前学单片机的经验告诉我,栈是因为在在这么一个特殊的物理结构下呈现的逻辑结构。但不管有没有这样一个物理上的空间结构,编程语言通过算法自己模拟实现了这样的逻辑结构。

一般使用栈,也都是用它的链式结构。所以,程序也只是链式的栈的程序。
首先,是定义一个栈的结构体:

typedef struct node{
	elementype data;
	struct node *next;
}node,* linkstack; 

值得说明的是,在这里设置的栈,是只能在表头插入和删除的单链表。在这种逻辑下,头节点本质上,并不是栈的top。第二个结点,才是栈的top。因为链表的头结点,是链表的寻址由来,是不能被插入和移动的嘛,所以就不能作为真正意义上的top。

各类函数:

elementype popStack(linkstack  lstack);
void pushStack(linkstack  lstack,elementype DatatoTop);
elementype readTop(linkstack  lstack);
void deleteStack(linkstack  lstack);
void printDataStack(linkstack  lstack);

出栈:

elementype popStack(linkstack  lstack)
{
	node * tempnode ;//= lstack->next;//= (node *)malloc(sizeof(node));
	elementype DataTop = 0;
	tempnode = lstack->next;
	//tempnode = lstack;
	
	if(tempnode == NULL){
		printf("the linkstack is null.\n");
		return 0;
	}
	
	lstack->next = tempnode->next;
	lstack->data--;
	
	printf("the data of top is %d\n",tempnode->data);
	
	DataTop = tempnode->data;
	free(tempnode);
	
	return DataTop;
}

入栈(里面的printf函数,是调试用的):

void pushStack(linkstack  lstack,elementype DatatoTop)
{
	//node * tempnode; 
	
	linkstack tempnode;
	tempnode  = (linkstack)malloc(sizeof(node));
	printf("succeed 1\n");
	
	tempnode->data = DatatoTop;
	//tempnode->next = NULL;
	printf("succeed 2\n");
	tempnode->next = lstack->next;
	printf("succeed 3\n");
	lstack->next = tempnode;
	printf("succeed 4\n");
	
	printf("succeed to push %d to stack\n",tempnode->data);
	lstack->data++;
}

读top的数据:

elementype readTop(linkstack  lstack)
{
	node * tempnode ;
	elementype DataTop = 0;
	tempnode = lstack->next;
	
		if(tempnode == NULL){
		printf("the linkstack is null.\n");
		return 0;
	}
	
	printf("the data of top is %d\n",tempnode->data);
	
	DataTop = tempnode->data;
	
	//这一行要做测试 ,我自己觉得free的话,会把内存free掉的 
	//free(tempnode);
	
	return DataTop;	
}

删除stack:

void deleteStack(linkstack lstack)
{
	node * tempnode;
	tempnode = lstack->next;
	while(tempnode->next != NULL){
		tempnode = tempnode->next;
		free(tempnode);
		lstack->data--;
	}
	
	lstack->next = tempnode->next;
	free(tempnode);
	lstack->data--;
	
	printf("the data of lstack is %d\n",lstack->data);
}

print整个栈:

void printDataStack(linkstack  lstack)
{
	node * tempnode;
	int num = 1;
	tempnode = lstack->next;
	printf("the data of lstack is %d\n",lstack->data);
	while(tempnode->next != NULL){
		printf("the data of %d is %d\n",num++,tempnode->data);
		tempnode = tempnode->next;
	}
	printf("the data of %d is %d\n",num++,tempnode->data);
	//tempnode = tempnode->next;
}

全部:

#include<stdio.h>
#include<malloc.h>

//#define elementype int
typedef int elementype;
/*
功能设计:
进栈、出栈、查长度、读栈顶元素 
*/

typedef struct node{
	elementype data;
	struct node *next;
}node,* linkstack; 


elementype popStack(linkstack  lstack);
void pushStack(linkstack  lstack,elementype DatatoTop);
elementype readTop(linkstack  lstack);
void deleteStack(linkstack  lstack);
void printDataStack(linkstack  lstack);

int main(void)
{
	int DatafromTop = 0;
	linkstack  lstack;
	
	//linkstack * tempstack ;
	lstack = (node*)malloc(sizeof(node));
	if(lstack == NULL){
		printf("fail to init\n");
	}
	//下面这行,就是说建立了一个空的链栈,事实上是只有个表头
	//(只是一个带头的而已,后面也不会存数据,不过可以计长度hhh),栈头栈底都没有, 
	lstack->next = NULL;
	lstack->data = 0;
	printf("succeed to init\n");
	
	pushStack(lstack,23);
	pushStack(lstack,22);
	pushStack(lstack,21);
	
	printDataStack(lstack);
	
	DatafromTop = popStack(lstack);
	printf("the DatafromTop is %d\n",DatafromTop);
	
	DatafromTop = readTop(lstack);
	printf("the DataofTop is %d\n",DatafromTop);
	printDataStack(lstack);
	
	return 0;
}


elementype popStack(linkstack  lstack)
{
	node * tempnode ;//= lstack->next;//= (node *)malloc(sizeof(node));
	elementype DataTop = 0;
	tempnode = lstack->next;
	//tempnode = lstack;
	
	if(tempnode == NULL){
		printf("the linkstack is null.\n");
		return 0;
	}
	
	lstack->next = tempnode->next;
	lstack->data--;
	
	printf("the data of top is %d\n",tempnode->data);
	
	DataTop = tempnode->data;
	free(tempnode);
	
	return DataTop;
}

void pushStack(linkstack  lstack,elementype DatatoTop)
{
	//node * tempnode; 
	
	linkstack tempnode;
	tempnode  = (linkstack)malloc(sizeof(node));
	printf("succeed 1\n");
	
	tempnode->data = DatatoTop;
	//tempnode->next = NULL;
	printf("succeed 2\n");
	tempnode->next = lstack->next;
	printf("succeed 3\n");
	lstack->next = tempnode;
	printf("succeed 4\n");
		
	printf("succeed to push %d to stack\n",tempnode->data);
	lstack->data++;
	
	
}



elementype readTop(linkstack  lstack)
{
	node * tempnode ;
	elementype DataTop = 0;
	tempnode = lstack->next;
	
		if(tempnode == NULL){
		printf("the linkstack is null.\n");
		return 0;
	}
	
	printf("the data of top is %d\n",tempnode->data);
	
	DataTop = tempnode->data;
	
	//这一行要做测试 ,我自己觉得free的话,会把内存free掉的 
	//free(tempnode);
	
	return DataTop;	
}

void deleteStack(linkstack lstack)
{
	node * tempnode;
	tempnode = lstack->next;
	while(tempnode->next != NULL){
		tempnode = tempnode->next;
		free(tempnode);
		lstack->data--;
	}
	
	lstack->next = tempnode->next;
	free(tempnode);
	lstack->data--;
	
	printf("the data of lstack is %d\n",lstack->data);
}

void printDataStack(linkstack  lstack)
{
	node * tempnode;
	int num = 1;
	tempnode = lstack->next;
	printf("the data of lstack is %d\n",lstack->data);
	while(tempnode->next != NULL){
		printf("the data of %d is %d\n",num++,tempnode->data);
		tempnode = tempnode->next;
	}
	printf("the data of %d is %d\n",num++,tempnode->data);
	//tempnode = tempnode->next;
}
``
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值