前言
临阵磨枪,不快也光。应付考试,大量摘抄课本内容,会陆续添加其他相关内容及代码。最后祝我考试顺利。
小结
栈
特性:先进后出
图中base:栈底指针;top:栈顶指针
顺序栈的实现 :
//本代码栈顶指针指向栈顶元素的后一元素
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10//顺序栈存储空间分配
typedef struct{
int *base;//栈底指针
int *top;//栈顶指针
int stacksize;//栈可用最大容量
}sqStacks;
sqStacks initStack(sqStacks s){//初始化
s.base=(int*)malloc(s.stacksize*sizeof(int));
if(!s.base) exit(0);//存储分配失败,终止程序
s.top=s.base;//top初始为base,空栈
s.stacksize=MAXSIZE;
printf("栈初始化成功\n");
return s;
}
sqStacks push(sqStacks s,int ele){//入栈
if(s.top-s.base==s.stacksize){
printf("栈满\n");
return s;
}
*s.top=ele;//元素压入栈顶
printf("%d入栈\n",*s.top);
s.top++;//栈顶指针加1
return s;
}
sqStacks pop(sqStacks s){//出栈
if(s.top!=s.base){
s.top--;
printf("%d出栈\n",*s.top);
return s;
}
printf("空栈\n");
return s;
}
int main()
{
sqStacks s;
s=initStack(s);
s=push(s,1);
s=push(s,2);
s=push(s,3);
s=pop(s);
s=pop(s);
s=pop(s);
s=pop(s);
return(0);
}
/* 标准输出:
栈初始化成功
1入栈
2入栈
3入栈
3出栈
2出栈
1出栈
空栈
*/
队列
特性:先进先出(First In First Out, FIFO)
//----- 队列的顺序存储结构-----
#define MAXSIZE 100;
typedef struct {
int *base;//存储空间的基地址
int front;//头指针
int rear;//尾指针
}sqQueue;
为了在 C 语言中描述方便起见,在此约定:初始化创建空队列时,令 front = rear = 0 , 每当插入 新的队列尾元素时,尾指针 rear增1; 每当删除队列头元素时, 头指针 front增1。因此,在非空队列 中,头指针始终指向队列头元素,而尾指针始终指向队列尾元素的下一个位置,如图 3.12所示。
假设当前队列分配的最大空间为 6, 则当队列处于图 3.12(d) 所示的状态时不可再继续 插入新的队尾元素,否则会出现溢出现象, 即因数组越界而导致程序的非法操作错误。 事实 上,此时队列的实际可用空间并未占满,所以这种现象称 为 “假溢出"。这是由 "队尾入队,队头出队” 这种受限制 的操作造成的。 怎样解决这种 “假溢出” 问题呢? 一个较巧妙的办法是将顺序队列变为一个环状的空间,如图 3.13 所示,称之为循环队列。
在图 3.14 (a) 中,队头元素是 J5, 在元素J6入队之前,在 Q.rear 的值为 5, 当元素J6入队之 后,通过 “模 ” 运算,Q.rear = (Q.rear + 1)%6, 得到 Q.rear 的值为 0, 而不会出现图 3.12(d) 的 “假溢出“ 状态。
在图 3.14(b) 中, J7、J8、J9、J10相继入队,则队列空间均被占满,此时头、尾指针相同。
在图 3.14 (c) 中, 若J5和J6相继从图 3.14(a)所示的队列中出队,使队列此时呈 “空 ” 的 状态, 头、尾指针的值也是相同的。由此可见,对于循环队列不能以头、尾指针的值是否相同来判别队列空间是 “满 ” 还是 “空 ”。 在这种情况下, 如何区别队满还是队空呢?
通常有以下两种处理方法:
(1)少用一个元素空间, 即队列空间大小为m时,有m-1个元素就认为是队满。这样判断队空的条件不变, 即当头、 尾指针的值相同时, 则认为队空;而当尾指针在循环意义上加1后是等于头指针,则认为队满。 因此,在循环队列中队空和队满的条件是:
队空的条件: Q.front = Q.rear
队满的条件: (Q rear+ 1)%MAXQSIZE = Q.front
如图 3.14 (d)所示,当J7、J8、J9 进入图 3.14(a)所示的队列后, (Q.rear+ 1)%MAXQSIZE的值等千 Q.front, 此时认为队满。
(2)另设一个标志位以区别队列是 “空 ” 还是 “满 "。
链队
链队是指采用链式存储结构实现的队列。通常链队用单链表来表 示,如图 3.15 所示。 一个链队显然需要两个分别指示队头和队尾的指 针(分别称为头指针和尾指针)才能唯一确定。 这里和线性表的单链表一样, 为了操作方便起见,给链队添加一个头结点, 并令头指针始终指向头结点。
链队源码
#include <stdlib.h>
#include <stdio.h>
#define MAXSIZE 100;
typedef struct {
int base;
struct sqQueue* next;
}sqQueue;
sqQueue* initQueue(){
sqQueue* queue=(sqQueue*)malloc(sizeof(sqQueue));
queue->next=NULL;
return queue;
}
sqQueue* enterQuence(sqQueue* queue,int data){
sqQueue* elem=(sqQueue*)malloc(sizeof(sqQueue));
elem->base=data;
elem->next=NULL;
queue->next=elem;
queue=elem;
printf("%d入队\n",data);
return queue;
}
sqQueue* delQueue(sqQueue* top,sqQueue* rear){
if(top->next==NULL){
printf("队列为空\n");
return rear;
}
sqQueue* q=NULL;
q=top->next;
printf("%d出队\n",q->base);
top->next=q->next;
if(rear==q){
rear=top;
}
free(q);
return rear;
}
int main()
{
sqQueue* queue=NULL,*top=NULL,*rear=NULL;
queue=top=rear=initQueue();
rear=enterQuence(rear,1);
rear=enterQuence(rear,2);
printf("----------------\n");
rear=delQueue(top,rear);
rear=delQueue(top,rear);
rear=delQueue(top,rear);
return(0);
}
参考书目:严蔚敏-《数据结构(C语言版)》