数据结构-栈

本文详细介绍了C语言中顺序栈和链栈的数据结构及其操作,包括栈的创建、初始化、入栈、出栈、取栈顶元素以及内存管理。通过实例展示了如何使用结构体和指针实现这两种栈的数据操作。
摘要由CSDN通过智能技术生成

栈本质上是一种受限制的线性表,先进后出。

从存储结构可以分成以下两种:顺序栈和链栈。简单点就是一个是数组形成的栈,另一个是链表形成的栈

1.顺序栈

1.创建栈的结构体

typedef int SElemType;
typedef struct
{
    SElemType *base;    // 栈底指针
    SElemType *top;     // 栈顶指针
    int stacksize;      // 栈可用的最大容量
} SqStack;

2.初始化操作

SqStack* InitStack(SqStack *S)//注意,这里很多书上写&取地址,但是c语言中处理不了,需要传入指针
{
    // 构造一个空表
    S->base = (SElemType*)malloc(MAXSIZE * sizeof(SElemType));
	
    if (!S->base) {
        exit(EXIT_FAILURE);  // 存储分配失败
    }
    S->top = S->base;       // top初始为base,空栈
    S->stacksize = MAXSIZE;  // stacksize置为栈的最大容量MAXSIZE
    return S;//返回的是整个栈的指针
}

int main() {
    SqStack s;//先构建一个代表栈的结构体
    SqStack* p = InitStack(&s);//将结构体地址传入
	printf("%d\t%d\n%d",p->base,p->top,p->stacksize);//还没数据,所以两个地址相同,为空表

    // 使用 p 操作栈...

    // 释放动态分配的内存
    free(p->base);

    return 0;
}

3.入栈

SqStack* push(SqStack* S,SElemType e)
{
	if(S->top-S->base==MAXSIZE)
	{
		exit(-1);
	}
	*S->top++=e;//^^^^^^^^^
	return S;
}

先解引用后进行指针上移,单目运算符的运算顺序从右向左。

4.出栈

SqStack* pop(SqStack* S,SElemType* p)
{
	if(S->top==S->base)
	{
		exit(-1);
	}
	*p=*--S->top;//先下移动,然后进行解引用
	return S;
}

入栈和出栈的时候会涉及到判断,如果想返回栈的同时也有判断的返回

因为返回值只能是一种类型 所以使用exit()

exit(0) 正常

exit(n)异常 (n不是0)

参考连接:C语言中的exit()函数_c语言exit-CSDN博客

5.取栈顶元素

SElemType gettop(SqStack* S)
{
	if(S->top!=S->base)
	{
		return *(S->top-1);
	}
	
}

6.完整代码

#include <stdio.h>
#include<stdlib.h>

typedef int SElemType;
#define MAXSIZE 100

typedef struct
{
    SElemType *base;    // 栈底指针
    SElemType *top;     // 栈顶指针
    int stacksize;      // 栈可用的最大容量
} SqStack;

SqStack* InitStack(SqStack *S)//注意,这里很多书上写&取地址,但是c语言中处理不了,需要传入指针
{
    // 构造一个空表
    S->base = (SElemType*)malloc(MAXSIZE * sizeof(SElemType));
	
    if (!S->base) {
        exit(EXIT_FAILURE);  // 存储分配失败
    }
    S->top = S->base;       // top初始为base,空栈
    S->stacksize = MAXSIZE;  // stacksize置为栈的最大容量MAXSIZE
    return S;//返回的是整个栈的指针
}


SqStack* push(SqStack* S,SElemType e)
{
	if(S->top-S->base==MAXSIZE)
	{
		exit(-1);
	}
	*S->top++=e;
	return S;
}

SqStack* pop(SqStack* S,SElemType* p)
{
	if(S->top==S->base)
	{
		exit(-1);
	}
	*p=*--S->top;
	return S;
}

SElemType gettop(SqStack* S)
{
	if(S->top!=S->base)
	{
		return *(S->top-1);
	}
	
}


int main() {
    SqStack s;//先构建一个代表栈的结构体
    SqStack* p = InitStack(&s);//将结构体地址传入
	printf("%d\t%d\n%d\n",p->base,p->top,p->stacksize);//还没数据,所以两个地址相同,为空表

    // 使用 p 操作栈...
	push(p,1);//入栈
	int b=gettop(p);
	printf("%d\t%d\n%d\t%d\n",p->base,p->top,p->stacksize,b);
	
	
	
	SElemType a=9;
	SElemType* pa=&a;
	SqStack* p1=pop(p,pa);
	printf("%d\t%d\n%d\t%d\n",p1->base,p1->top,p1->stacksize,a);//出栈
	
	
	

    // 释放动态分配的内存
    free(p->base);

    return 0;
}


输出结果

28029536	28029536
100
28029536	28029540
100	1
28029536	28029536
100	1

2.链栈

1.创建结构体

typedef struct snode
{
	int data;
	struct snode* next;
	
}snode,*linkstack;

如果使用typedef重新命名之后,尽量统一使用一个名称,不然编译器经常出现指针指向不明确的警告

2.初始化(无头结点)

linkstack init()
{	
	linkstack s;//创建指针
	s=NULL;//指针指向空
	return s;
}

这里创建的为无头结点的链栈,头结点的存在不是很有必要。(头指针,头结点,首元节点需要分清)

一般将链表的头作为栈顶(top)

3.入栈

linkstack push(linkstack s,int e)
{
	linkstack p=(snode*)malloc(sizeof(snode));
	p->data=e;
	p->next=s;
	s=p;
	return s;
	
}

创建空间——赋值——先调整会变化的指针(s->next指p,s变则p变化)——再调整不会变的(s)

和头插法创建链表很相似

4.出栈

linkstack pop(linkstack s,int* e)
{
	if(s==NULL) exit(-1);
	*e=s->data;
	linkstack q=s;
	s=s->next;
	free(q);
	return s;
}

类似于删除链表节点

创建指针存放节点——跨过该节点——删除节点空间

5.取栈顶元素

int gettop(linkstack s)
{
	if(s!=NULL)
	return s->data;
}

6.完整代码如下

#include <stdio.h>
#include<stdlib.h>

typedef struct snode
{
	int data;
	struct snode* next;
	
}snode,*linkstack;



linkstack init()
{	
	linkstack s;//创建指针
	s=NULL;//指针指向空
	return s;
}

linkstack push(linkstack s,int e)
{
	linkstack p=(snode*)malloc(sizeof(snode));
	p->data=e;
	p->next=s;
	s=p;
	return s;
	
}
linkstack pop(linkstack s,int* e)
{
	if(s==NULL) exit(-1);
	*e=s->data;
	linkstack q=s;
	s=s->next;
	free(q);
	return s;
}
void showlist(snode* l)
{
	snode* p=l;
	while(p)
	{
		printf("%d\n",p->data);
		p=p->next;
		
	}
	printf("数据已经输出完毕\n");
}

int gettop(linkstack s)
{
	if(s!=NULL)
	return s->data;
}


int main()
{
	
  linkstack s1=init();
	
	linkstack s2=push(s1,3);
	showlist(s2);
	linkstack s3=push(s2,2);
	showlist(s3);//类似上篇文章中的头插法来添加链表数据
	
	int* p=(int*)malloc(sizeof(int));//需要一段空间来储存出栈数据
	linkstack s4=pop(s3,p);
	printf("%d\t",*p);
	showlist(s4);//
    
	printf("%d",gettop(s4));
	
   
   return 0;
}

输出结果

3
数据已经输出完毕
2
3
数据已经输出完毕
2	3
数据已经输出完毕
3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值