今天是我开始博客之旅的第一天,被小学期题目给难倒了,打算总结总结以此提高自己
停车场问题
设停车场内只有一个可停放n辆汽车的狭长通道,且只有一个大门可供汽车进出。汽车在停车场内按车辆到达时间的先后顺序,依次由北向南排列大门在最南端,最先到达的第一辆车停放在车场的最北端),○1若车场内已停满n辆汽车,则后来的汽车只能在门外的便道上等候,一旦有车开走,则排在便道上的第一辆车即可开入;○2当停车场内某辆车要离开时,在它之后开入的车辆必须先退出车场为它让路,待该辆车开出大门外,其它车辆再按原次序进入车场,○3每辆停放在车场的车在它离开停车场时必须按它停留的时间长短交纳费用。
【实现提示】
综合利用栈和队列模拟停车场管理,学习利用栈和队列解决实际问题。
1.栈
2.队列
3.综合运用
一、 栈:
定义:栈作为一种限定性线性表,是将线性表的插入与删除操作限定在栈的一端进行,通常将能进行插入与删除操作的一段称作栈顶(top),其当前位置是动态变化的,由一个称为栈顶指针的位置指示器来指示。栈的另一端称为栈底(bottom),栈底是一直固定不动的。栈大体有顺序栈和链栈两种。
进栈操作:每次进栈元素都被放在栈顶元素之上而成为一个新的栈顶。
出栈操作:当前栈中最新的元素出栈。
具体操作方法:
顺序栈:
1.存储结构的定义:
#define Stack_size 1000 //一次能容纳的最大值
**typedef int Elemtype;** /*这一行解释了Elemtype为什么能定义一个变量,它和int类型等同,使用这一行而不直接用int的目的,我觉得是为了方便以后更改为其他类型*/
typedef struct
{
Elemtype elem[Stack_size];//用来存放栈中元素的一维数组
int top;//用来存放栈顶元素的下标,top=-1表示空栈
}Seqstack;
2.初始化:
void Init(Seqstack *S)//使用了一个顺序栈指针型的变量S,指针型变量可以操作地址,有时更加方便
{
S->top=-1; //这里用的是“->”而不是 “.”了,这就是指针型和其他类型的区别之一
}
3.进栈:
int Push(Seqstack *S, Elemtype x)//进栈
{
if(S->top==Stack_size-1)//表示栈已满 ,如果栈满后继续入栈则会发生上溢
return FALSE;
else
{
S->top++;//栈顶指针先往上移一位,第一次从-1到0
S->elem[S->top]=x;//x进栈,第一次进入的是最底下,top=0的位置 ,top=-1的时候表示的是空栈,不能进入
return TRUE;
}
}
4.出栈:
出栈时,首先判断当前栈是否为空,如果为空,则出栈时则会发生下溢
int Pop(Seqstack *S, Elemtype *x) //出栈,弹出
{//指针型的x的目的是能够保存元素的地址
if(S->top==-1)//空栈时无法再删除
return FALSE;
else
{
*x=S->elem[S->top];//栈顶元素赋值给x
S->top--;//栈顶指针下移一位
return TRUE;
}
}
5.读栈顶元素
int Gettop(Seqstack *S, Elemtype *x) //读栈顶,不是删除栈顶,S->top不用操作
{
if(S->top==-1)//空栈时无法再读
return FALSE;
else
{
*x=S->elem[S->top];//栈顶元素赋值给x
return TRUE;
}
}
注意:在实现Gettop操作时,也可将参数说明Seqstack *S改为Seqstack S,也就是将传地址方式改成了传值方式。传值比传地址容易理解,但传地址比传值更节省空间与时间。
6.打印元素,即输出
void print(Seqstack *S)//打印数据
{
for(int i=0;i<=S->top;i++)//循环输出
{
printf("%d ",S->elem[i]);
}
printf("\n");
}
7.主函数的书写:
我觉得主函数是一个程序里最考验逻辑的部分,它得连接各个方法,让各个方法能运行,然后呢,方法之间还得有一些说明性文字让人能明白进行到哪一步了,我一般写主函数的时候花的时间最长。
int main()
{
Seqstack *S;
S=(Seqstack *)malloc(sizeof(Seqstack )); **//这个地方我有些不懂,望各位能解答一下,谢谢!**
int x;//进栈的元素
int n;//进栈元素的个数
int m;//出栈
Init(S);
printf("请输入进栈元素个数: \n");
scanf("%d",&n);
printf("请输入进栈的元素:\n");
for(int i=0;i<n;i++)
{
scanf("%d",&x);
Push(S,x);
}
print(S);
printf("请输入出栈元素的个数: \n");
scanf("%d",&n);
for(int i=0;i<n;i++)
{
Pop(S,&x);
}
print(S);
}
8.程序
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
#define Stack_size 1000 //一次能容纳的最大值
typedef int Elemtype;
typedef struct
{
Elemtype elem[Stack_size];//用来存放栈中元素的一维数组
int top;//用来存放栈顶元素的下标,top=-1表示空栈
}Seqstack;
void Init(Seqstack *S)//初始化
{
S->top=-1;
}
int Push(Seqstack *S, Elemtype x)//进栈,压入
{
if(S->top==Stack_size-1)//表示栈已满
return FALSE;
else
{
S->top++;//栈顶指针先往上移一位,第一次从-1到0
S->elem[S->top]=x;//x进栈,第一次进入的是最底下,top=0的位置 ,top=-1的时候表示的是空栈,不能进入
return TRUE;
}
}
int Pop(Seqstack *S, Elemtype *x) //出栈,弹出
{//指针型的x的目的是能够保存元素的地址
if(S->top==-1)//空栈时无法再删除
return FALSE;
else
{
*x=S->elem[S->top];//栈顶元素赋值给x
S->top--;//栈顶指针下移一位
return TRUE;
}
}
int Gettop(Seqstack *S, Elemtype *x) //读栈顶,不是删除栈顶,S->top不用操作
{
if(S->top==-1)//空栈时无法再读
return FALSE;
else
{
*x=S->elem[S->top];//栈顶元素赋值给x
return TRUE;
}
}
void print(Seqstack *S)//打印数据
{
for(int i=0;i<=S->top;i++)//循环输出
{
printf("%d ",S->elem[i]);
}
printf("\n");
}
int main()
{
Seqstack *S;
S=(Seqstack *)malloc(sizeof(Seqstack ));
int x;//元素
int n;//元素的个数
Init(S);
printf("请输入进栈元素个数: \n");
scanf("%d",&n);
printf("请输入进栈的元素:\n");
for(int i=0;i<n;i++)
{
scanf("%d",&x);
Push(S,x);
}
printf("栈内元素为: \n");
print(S);
printf("请输入出栈元素的个数: \n");
scanf("%d",&n);
printf("剩余栈内元素为: \n");
for(int i=0;i<n;i++)
{
Pop(S,&x);
}
print(S);
}
链栈
链栈即采用链表作为储存结构实现的栈。为便于操作,这里采用带头结点的单链表实现栈,由于栈的插入和删除操作都只在表头进行,所以用栈顶指针作为表头指针。
具体操作:
1.存储结构的建立
#define TRUE 1 //TRUE代表1
#define FALSE 0 //FALSE代表0
typedef int Elemtype;
typedef struct node//存储结构的建立
{
Elemtype data;
struct node *next;//递归
}linkstacknode,* linkstack;
2.初始化:
void Init(linkstack top)//初始化链表
{
top->next=NULL;
}
3.进栈:
一个元素进栈,不能平白无依据就进去了,它得依靠一个介质才能进入栈,顺序栈是靠一个数组,那么链栈是靠结点,结点的数据域储存着该数据
int Push(linkstack top,Elemtype x)
{
linkstacknode *temp;//定义一个结点
temp=(linkstacknode *)malloc(sizeof(linkstack));//为结点申请空间分配
if(temp==NULL)
return FALSE;//申请空间不成功,就是栈满的意思
else
{
temp->data=x;//数据域赋值
temp->next=top->next;//将top的指针域内的地址赋值给temp的指针域
top->next=temp;//将temp的地址赋值给top的指针域
return TRUE;
}
}
4.出栈:
int Pop(linkstack top,Elemtype *x)
{
linkstacknode *temp;
temp=top->next;//将top指针域的地址给了temp,意思是temp可以代表首结点
if(temp->next==NULL)
{
return FALSE;
}
else
{
*x=temp->data;//弹出数据
top->next=temp->next; /*直接让temp的指针域的地址给了top的指针域,
意思是跨过temp这个结点,那么temp结点 就被删除了*/
}
free(temp);
return TRUE;
}
5.读栈顶元素
该方法相对简单,就是定义一个结点,将top的指针域所指地址赋给temp,然后就可以读取temp的数据域的值了。
int Gettop(linkstack top,Elemtype *x)
{
linkstacknode *temp;
temp=top->next;
*x=temp->data;
printf("%d \n",*x);
return TRUE;
}
6.打印输出
void print(linkstack top)
{
linkstacknode *temp; //有一个媒介temp
temp=(linkstacknode *)malloc(sizeof(linkstacknode));
temp=top->next; //temp为首元结点
while(temp!=NULL)
{
printf("%d ",temp->data);
temp=temp->next;//temp向后移动
}
free(temp);
printf("\n");
}
7.主函数的书写:
int main()
{
int x;
int n;
linkstack top;
top=(linkstack)malloc(sizeof(linkstacknode));//申请空间
Init(top);
printf("请输入进栈元素个数: \n");
scanf("%d",&n);
printf("请输入进栈的元素:\n");
for(int i=0;i<n;i++)
{
scanf("%d",&x);
Push(top,x);
}
printf("栈内元素为: \n");
print(top);
printf("栈顶元素为:\n");
Gettop(top,&x);
printf("请输入出栈元素的个数: \n");
scanf("%d",&n);
printf("剩余栈内元素为: \n");
for(int i=0;i<n;i++)
{
Pop(top,&x);
}
print(top);
}
8.程序:
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
typedef int Elemtype;
typedef struct node//存储结构的建立
{
Elemtype data;
struct node *next;//递归
}linkstacknode,* linkstack;
void Init(linkstack top)//初始化链表
{
top->next=NULL;//链表的初始化就是令链表头结点的指针域为空;与顺序栈不同
}
/*一个元素进栈,不能平白无依据就进去了,它得依靠一个介质才能进入栈,
顺序栈是靠一个数组,那么链栈是靠结点,结点的数据域储存着该数据*/
int Push(linkstack top,Elemtype x)
{
linkstacknode *temp;//定义一个结点
temp=(linkstacknode *)malloc(sizeof(linkstacknode));//为结点申请空间分配
if(temp==NULL)
return FALSE;//申请空间不成功,就是栈满的意思
else
{
temp->data=x;//数据域赋值
temp->next=top->next;//将top的指针域内的地址赋值给temp的指针域
top->next=temp;//将temp的地址赋值给top的指针域
return TRUE;
}
}
int Pop(linkstack top,Elemtype *x)
{
linkstacknode *temp;
temp=top->next;//将top指针域的地址给了temp,意思是temp可以代表首结点
if(temp->next==NULL)
{
return FALSE;
}
else
{
*x=temp->data;//弹出数据
top->next=temp->next; /*直接让temp的指针域的地址给了top的指针域,
意思是跨过temp这个结点,那么temp结点 就被删除了*/
}
free(temp);
return TRUE;
}
int Gettop(linkstack top,Elemtype *x)
{
linkstacknode *temp;
temp=top->next;
*x=temp->data;
printf("%d \n",*x);
return TRUE;
}
void print(linkstack top)
{
linkstacknode *temp; //有一个媒介temp
temp=(linkstacknode *)malloc(sizeof(linkstacknode));
temp=top->next; //temp为首元结点
while(temp!=NULL)
{
printf("%d ",temp->data);
temp=temp->next;//temp向后移动
}
free(temp);
printf("\n");
}
int main()
{
int x;
int n;
linkstack top;
top=(linkstack)malloc(sizeof(linkstacknode));//申请空间
Init(top);
printf("请输入进栈元素个数: \n");
scanf("%d",&n);
printf("请输入进栈的元素:\n");
for(int i=0;i<n;i++)
{
scanf("%d",&x);
Push(top,x);
}
printf("栈内元素为: \n");
print(top);
printf("栈顶元素为:\n");
Gettop(top,&x);
printf("请输入出栈元素的个数: \n");
scanf("%d",&n);
printf("剩余栈内元素为: \n");
for(int i=0;i<n;i++)
{
Pop(top,&x);
}
print(top);
}
这一篇先介绍栈,下一篇再介绍队列。拜拜啦。