数据结构之栈

 顺序储存和链式储存


基础:结构体,数组,指针。

本文编译环境:Dev c++ 5.4.0

语言:c

序言:栈的操作和我上一篇介绍线性表的博客基本没什么区别,都是先进先出的操作。栈的操作分为创建,进栈,出栈,读顶,判断栈的状态和显示

#include<stdio.h>
#include<stdlib.h>
#define MAXLEN 100
#define datatype int 
//结构体的建立
typedef struct
{
	datatype data[MAXLEN];//数据存储 
	int top;//栈顶指针 
}Seqlist;//名字




//顺序栈创建 
Seqlist *Createlist()
{
	Seqlist *Lq;//定义栈顶指针 
	Lq=(Seqlist *)malloc(sizeof(Seqlist));//给栈顶指针分配空间 
	Lq->top=-1;//栈初始化为-1 
	return Lq;//返回栈顶指针 
} 




//进栈 
int Judg(Seqlist *Lq);//声明一下调用 




int Push(Seqlist *Lq,datatype i)//引入头指针和要进栈元素 
{
	if(Judg(Lq)==0) printf("Wrong!!! push!!!");//输出错误提示 
	else
	{
		Lq->top++;//栈顶指针加一 
		Lq->data[Lq->top]=i;//赋值 
	}
} 
//出栈并读顶 
int Popr(Seqlist *Lq,int *i)//引入栈顶指针和要输出的栈顶数据 
{
	if(Judg(Lq)==-1) printf("Wrong!!! pop!!!");//输出错误提示 
	else
	{
		*i=Lq->data[Lq->top];//通过地址赋值,读顶 
		Lq->top--;//栈顶指针减一 
	}
} 


 //单独读顶 
int Pop(Seqlist *Lq,int *i)//引入栈顶指针和要输出的栈顶数据 
{
      *i=Lq->data[Lq->top];//通过地址赋值,读顶 
} 


//判断 
int Judg(Seqlist *Lq)//引入栈顶指针
{
	if(MAXLEN-1==Lq->top) return 0;//栈满 
	else if(Lq->top==-1) return -1;//栈空 
	else return 1;//栈其他正常情况 
} 




//显示
void Looklist(Seqlist *Lq)//引入栈顶指针 
{
	int i;
	for(i=Lq->top;i>=0;i--)
	{
		printf("%d\n",Lq->data[i]);//输出 
	}
} 
int main()
{
	Seqlist *Lq;
	Lq=Createlist();//创建栈顶指针 
	Push(Lq,12);//入栈 
	Push(Lq,32);//入栈 
	Push(Lq,18);//入栈 
	Push(Lq,91);//入栈 
	Looklist(Lq);//查看所有 
	int x;
	Popr(Lq,&x);//出栈 
	printf("--%d--\n",x);//出战元素 
	Looklist(Lq);//查看 
	return 0;
} 

线性表就是个数组操作,删除和插入操作部分利用循环进行数据覆盖,优点是创建简单,缺点是局限性很大,必须先开垦一部分内存,不管用没用的到,而且很容易溢出。再比较下一个方法这些缺点就解决掉了。

相比线性栈,线性链栈就显得重要的多,这里重点强调一下线性链栈的六个操作方法。

#include<stdio.h>
#include<stdlib.h>
#define MAXLEN 100
#define datatype int 
//结构体的建立
typedef struct Seq
{
	datatype data;//数据存储 
	struct Seq *next;//指针指向下一个 
}Seqlist;//名字


//结构体的建立
typedef struct
{
	Seqlist *top;//栈顶指针 
}Link;//名字


//进栈 
int Push(Link &s,datatype i)//引入头指针和要进栈元素 
{
	Seqlist *a=(Seqlist *)malloc(sizeof(Seqlist));//分配空间 
	a->data=i;//输入数据 
	a->next=s.top;//把其他元素,插入到后边 
	s.top=a;//栈顶指针置顶 
} 
//出栈 
int Pop(Link &s,datatype &i)//引入头指针和要进栈元素 
{
	if(s.top==NULL) return 0;//判断是否为空 
	else
	{
		Seqlist *a=s.top; //临时指针 
		i=a->data;//返回出栈元素 
		s.top=a->next;//栈顶指针重置 
		delete a;//删除空间 
		return 1;
	}
} 
//显示
void Looklist(Link s)//引入栈顶指针 
{
	Seqlist *p=s.top; 
	while(p!=NULL)
	{
		printf("%d\n",p->data);//输出 
		p=p->next;//往下遍历 
	}
} 
int main()
{
	Link Lq;
	Lq.top=NULL;//初始化 
	Push(Lq,12);//入栈 
	Push(Lq,32);//入栈 
	Push(Lq,18);//入栈 
	Push(Lq,91);//入栈 
	Looklist(Lq);//查看所有 
	int a,x;
	if(Pop(Lq,x)) printf("%d %d\n",a,x);//出栈 
	Looklist(Lq);//查看所有 
	return 0;
} 

在这里再给大家忠告:判断的时候一定要写双等于,重点标注那里,作者少写一个等号,导致下边指针传递一直错误,而且在这里编译器是不会报判断错误的,只会报指针的使用错误,使我郁闷半天,一致怀疑对指针的理解!!!!

在指针上,我再介绍下,地址吧,通过实参修改形参,也就是通过地址修改值。

#include<stdio.h> 
void first(int q) 
{
	q=20;
}
void second(int &q) 
{
	q=30;
}
void third(int *q) 
{
	*q=40;
}
int main()
{
	int qw=10; 
	printf("未改变之前---%d---\n",qw);
	first(qw);
	printf("第一次改变---%d---\n",qw);
	second(qw);
	printf("第二次改变---%d---\n",qw);
	third(&qw);
	printf("第三次改变---%d---",qw);
	return 0;
}

结果:




first方法传递了qw但是只是读取了形参,在first方法里参数的地址并不一样,所以修改并没有什么影响。

second方法传递了qw,读取的是qw的实际地址,这点可以理解为,scanf输入的形式。直接在&qw地址进行修改,实参是&qw,所以形参就是qw。

third方法则是用到了指针,传递的只是qw地址,其前两种方法实参和形参都传递了,只是读取的不一样,在这里,就只是传递了地址,接受的使用指针指向的,相当于定义*q=&qw,所以q保存的是地址,*q是实参,只要修改*q就可以。

这些代码都是跑过的,建议大家还是自己亲手敲一遍加深印象,作者这里也是一字一字敲出来的,要避免眼高手低。

本章的内容有误或者不懂的地方,大家可以私信我,我也会第一时间回复大家的,差不多暑假两个月,复习下这些基本知识,其他的问题也可以问我,就算我不知道的,在能力范围之内的一定竭尽全力为你们解答。我的QQ:932824098.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值