栈和队列是两种最重要的数据结构,也是两种最典型的抽象数据类型,应用非常的广泛。
目录
一、栈
一、空栈的创建
二、进栈
三、出栈
二、队列
一、创建空队列
二、队列的入队和出队
三、取队列头元素
栈是一种特殊的线性表,其只允许在一端对表进行插入和删除操作,表中允许插入和删除操作的一端称为栈顶,另一端称为栈底,当栈中没有元素时,称为空栈。
栈的插入操作通常成为进栈或入栈,栈的删除操作通常称为出栈或退栈。
根据栈的定义,每次删除的总是“最年轻”的元素,即最后插入的元素。而最先插入的元素则会被压在底部,直到所有插入的元素都被删除后才能删除。因此,栈又被称为后进先出表或下推表。
栈的顺序表示中,空栈的创建与空顺序表的创建类似,唯一不同的是空顺序表中元素数量n的值初始化为0,而空栈这里则初始化为-1。
typedef int DataType;
struct SeqStack {
int MAXNUM;
int t;
DataType* s;
};
typedef struct SeqStack* PSeqStack;
PSeqStack createEmptyStack() //创建空栈
{
PSeqStack pastack = (PSeqStack)malloc(sizeof(struct SeqStack));
if (pastack != NULL)
{
pastack->s = (DataType*)malloc(sizeof(DataType) * pastack->MAXNUM);
if (pastack->s)
{
pastack->MAXNUM = 13;
pastack->t = -1;
return pastack;
}
else free(pastack);
}
cout << "错误!" << endl;
return NULL;
}
其代码书写基本与空顺序表的创建一致!
由于栈是一种动态结构,因此,当栈中已经有MAXNUM个元素的时候,如果再做进栈运算,则会产生溢出,成为上溢。
为了避免溢出,在对栈进行进栈操作时,需判断栈是否已满。
void push_seq(PSeqStack pastack, DataType a) //进栈
{
if (pastack->t >= pastack->MAXNUM - 1) //因存放元素序号从0开始,故应与MAXNUM-1做比较
cout << "上溢" << endl;
else {
pastack->t = pastack->t + 1;
pastack->s[pastack->t] = a;
}
}
前面提到上溢,其实对空栈进行出栈操作时也会产生溢出,称为下溢,故进行出栈操作之前,也需要对栈进行判空。
void pop_seq(PSeqStack pastack) //出栈
{
if (pastack->t == -1)
{
cout << "下溢" << endl;
}
else {
pastack->t = pastack->t - 1;
}
}
这里我们与顺序表中的操作不同,顺序表中删除操作要求整体移位,我们栈中,当栈不为空时,通过将栈顶变量减一即可达到删除元素的目的。这里需要进行说明一下,所谓删除,只是将栈顶位置往前移动了一个位置,这样原来栈顶的元素就可以不认为在栈中了,实际上原来元素还占据着原来位置,当新的元素进栈时便会将其覆盖掉。
队列也是一种特殊的线性表,其只允许在一端进行插入元素操作,再另一端进行删除元素操作,其中,插入元素的一端称为队头,删除元素的一端称为队尾,当队列中没有元素时,则称为空队。
队列的插入操作通常称为入队,删除操作称为出队。
队列同现实生活中的排队相同,只有从队尾开始排队,队头的最先离开。即当前“最老的”成员。故队列也被称为“先进先出表”。
创建空队列与创建空栈不同,它需要创建两个量表分别指示队头和队尾元素的位置。这里为了算法的方便,约定队头f指出实际队头元素的位置,而队尾r指出实际队尾元素所在的位置的下一个位置。
typedef int DataType;
struct SeqQueue {
int MAXNUM;
int f,r;
DataType* s;
};
typedef struct SeqQueue* PSeqQueue;
PSeqQueue createEmptyQueue(int max) //创建空队列
{
PSeqQueue pqueue = (PSeqQueue)malloc(sizeof(struct SeqQueue));
if (pqueue != NULL)
{
pqueue->s = (DataType*)malloc(sizeof(DataType)*max);
if (pqueue->s)
{
pqueue->MAXNUM = max;
pqueue->f = 0;
pqueue->r = 0;
cout << "创建成功" << endl;
return pqueue;
}
else free(pqueue);
}
cout << "创建失败" << endl;
return NULL;
}
在顺序表示的队列中,同栈一样存在队列溢出的问题。当队列满是,再做入队操作,这种现象称为上溢;而当空队时,对队列进行出队的操作,而会导致下溢。这些现象在算法中都要考虑。
void enQueue_seq(PSeqQueue pqueue, DataType data) //进队列
{
if ((pqueue->r + 1) % pqueue->MAXNUM == pqueue->f)
cout << "队列已满" << endl;
else {
pqueue->s[pqueue->r] = data;
pqueue->r = (pqueue->r + 1) % pqueue->MAXNUM;
}
}
void deQueue_seq(PSeqQueue pqueue) //出队列
{
if (pqueue->f == pqueue->r) cout << "队列为空" << endl;
else {
pqueue->f = (pqueue->f + 1) % pqueue->MAXNUM;
}
}
当对垒不为空时,去队列头部的元素,队列本身保持不变。
DataType headQueue_seq(PSeqQueue pqueue)
{
if (pqueue->f == pqueue->r)
cout << "数据为空" << endl;
else {
return pqueue->s[pqueue->f];
}
}