基础:结构体,数组,指针。
本文编译环境: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.