栈
栈:栈是一种先进后出的线性结构。只允许在表尾进行插入或删除
逻辑结构:顺序结构
储存结构:顺序储存(顺序栈);链式储存(链栈)
栈的特点:先进后出(first in last out————又成为FILO表)
后进先出 (last in first out———LIFO表)
栈的输出应用
栈是可以进出一起的,例如DECBA,就可以先输入ABCD输出D,再输入E,输出ECBA
即可输出DECBA。
1.1顺序栈(静态申请)
顺序栈:储存结构采用顺序储存的栈,和顺序表类似
顺序栈的空间是先前定义好的,不可以像链表那杨边插入边申请空间。
栈顶:是指最顶端元素的下表由指针top实现。
栈底;指向栈的末尾。
栈在申请时用函数MAXSIZE来确定好空间。
栈结构的定义
typedef struct stack
{
int data[MAXSIZE];
int top;
}*stack_list;
//c创建
stack_list create_stack();
1.2顺序栈的操作
进栈(push):插入操作。通过指针 top++ 来实现
//入栈
int push(stack_list list,int element)
{
if(list->top==MAXSIZE-1||NULL==list)
{
puts("错误");
return -1;
}
list->data[++list->top]=element;
return 0;
}
出栈(pop):删除操作。通过指针 top--来实现,
注意:此刻的值并非真的删除,只是指针下移后无法显示,等下次输入时,又会将值覆盖。
//删除
void pop(stack_list list)
{
if(NULL==list||-1==list->top)
{
puts("错误");
return;
}
printf("删除的元素是%d\n",list->data[list->top]);
list->top--;
}
输出
//输出
void output(stack_list list)
{
if(list==NULL||list->top==-1)
{
puts("错误");
return ;
}
for(int i=0;i<=list->top;i++)
{
printf("%d\t",list->data[i]);
}
puts("");
}
1.3链栈(动态申请)
链栈:采用链式储存结构的栈,链栈采用单链表来实现,故不存在满上溢现象。
链栈的头插和删除相当于单链表的头插头删,此时的栈顶就是单链表的头。
栈链的尾插和尾删相当于单链表的尾差和尾删,刺客栈顶就是链表尾。
头插
Linklist insert_head(Linklist L,int element)
{
//创dd建新节点s
Linklist s=create_node();
//1,如果没有节点
if( NULL == L)
{
s->data=element;
L=s;
}
else//存在1个或多个节点
{
s->next=L->next;
L->next=s;
s->data=L->data;
L->data=element;
}
return L;
}
头删
//头删
Linklist delete_head(Linklist L)
{
//1,链表为空
if(NULL ==L)
{
puts("stack empty");
return NULL;
}
//2,只有一个节点
else if(NULL == L->next)
{
printf("出栈的元素是:%d\n",L->data);
free(L);L=NULL;
}
//3,存下多个节点(>=2)
else
{
Linklist q=L->next;
printf("出栈的元素是:%d\n",L->data);
L->data=q->data;
L->next=q->next;
free(q);
q=NULL;
}
return L;
}
输出
//遍历
void stack_link_output(Linklist L)
{
if(NULL ==L)
{
puts("ERROR");
return;
}
//2.循环
Linklist p=L;
while(p!=NULL)
{
printf("%d\t",p->data);
p=p->next;
}
puts("");
}
队列
队列:是一种先进先出的的线性结构,只允许在一端插入和删除,双端除外
删除的一端是对头,插入的一端是队尾。类似于火车。
逻辑结构:线性结构
储存结构:顺序储存(顺序队列和循环队列),链式储存(链式队列)
队列的特点:先进先出(first in first out)FIFO表
后进后出(last in last out)LILO表
1.1顺序队列
顺序队列采用顺序结构,和顺序表相似,存在假溢出现象,储存空间创建处就规定好了。
队头front:第一个元素的下表
队尾rear:最后一个元素的后面的下表,方便后面元素插入。
顺对队列的创立和插入
//创建
queue_list create_queue()
{ queue_list list=(queue_list)malloc(sizeof(struct queue));
if( NULL==list)
return NULL;
//为数据元素清零
memset(list->data,0,sizeof(list->data));
list->front=list->rear=0;
return list;
}
//输入
queue_list enqueue(queue_list L,int element)
{
if(L->rear==MAXSIZE||NULL==L)
{
puts("错误");
return L;
}
L->data[L->rear++]=element;
return L;
}
删除
//删除
queue_list shanchu(queue_list L)
{
if(NULL==L||L->front==L->rear)
{
puts("错误");
return L;
}
printf("删除的数为%d\n",L->data[L->front++]);
return L;
}
输出
//输出
queue_list shuchu(queue_list L)
{
if(NULL==L||L->front==L->rear)
{
puts("错误");
return L;
}
for(int i=L->front;i<L->rear;i++)
{
printf("%d\t",L->data[i]);
}
puts("");
return L;
}
1.2循环队列
循环队列在队空和队满时,都是队头指针和队尾指针指向同一个位置,即:front==rear 为了区分这两种情况,可以少用一个存储空间,队空的判断条件不变,以队尾指针rear加1等于队头指针为队列的判满条件。即:
◆ rear所指的单元始终为空。
◆ 循环队列为空:front=rear 。
◆ 循环队列满:(rear+1)%maxsize =front。
还可以使用标志量的方法来克服队列的“假溢出”现象
利用(L->rear%MAXSIZE)从而来做到循环
2.3链式队列
顺序队列存在假溢出现象,用循环队列解决,但循环队列会满,故采用链式队列解决。
储存结构:链式储存
和单链表相比,头插头删,则队头是链表尾
尾插尾删,对头则是链表头。
采用二级指针的方式,可让rear永远在队尾。
作业:计算 循环队列长度
int a=jisuan(L);
if(a==-1||a==0)
{
printf("长度为0");
}
else
printf("长度为%d",a);
//计算循环队列长度
int jisuan(queue_list L)
{if(L==NULL)
return -1;
int a=(MAXSIZE-L->front+L->rear)%MAXSIZE;
}