一.
栈是一种特殊的线性表,特点是:后进先出(LIFO),先进栈的元素后出栈,后进栈的元素先出。基本操作:栈的初始化、判断栈空、入栈、出栈等。比如,堆放一堆书,取出来的当然是第一本了,一本书放到这个书堆也是放在最上面,当然,你要是抽出来。。。。那我也没办法
栈的存储方式有两种,一个是用数组存储,另外一种是使用链表存储。使用数组存储需要注意判断栈的上溢或者下溢。上溢:超过了数组的大小。下溢:数组中已经没有元素仍执行弹出操作。使用链表存储的时候则没有上溢这个概念,因为链表毕竟是用一个加一个节点接上去。
栈的操作:
InitStack(SqStack &S);//初始化栈
DestroyStack(SqStack &S) ;//销毁栈
ClearStack(SqStack &S);//清空栈
StackLength(SqStack S);//返回栈的长度
StackEmpty(SqStack S);//判断栈是否是空
GetTop(SqStack S, ElemType &e);//获取栈首元素
Push(SqStack &S, ElemType e);//把元素压入栈顶
Pop(SqStack &S, ElemType &e);//弹出栈首元素,并返回该值
数组栈实现代码如下:
#include <iostream>
using namespace std;
#include <malloc.h>
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int ElemType;
typedef int Status;
typedef struct {
ElemType *base;
ElemType *top;
int stacksize;
}SqStack;
Status InitStack(SqStack &S) //初始化栈,申请空间
{
S.base = (ElemType *)malloc(sizeof(ElemType)*STACK_INIT_SIZE);
S.stacksize = STACK_INIT_SIZE; //栈的初始大小
S.top = S.base; //初始化的时候栈顶指针指向底部
return OK;
}
Status DestroyStack(SqStack &S) //销毁栈
{
free(S.base);
S.base = S.top = NULL;
S.stacksize = 0;
return OK;
}
Status ClearStack(SqStack &S) //清空栈
{
S.top = S.base;
return OK;
}
int StackLength(SqStack S) //返回栈的长度
{
return S.stacksize;
}
int StackEmpty(SqStack S) //判断栈是否是空
{
if(!S.stacksize)
{
return FALSE;
}
else
{
return TRUE;
}
}
ElemType GetTop(SqStack S, ElemType &e) //获取栈首元素
{
if(S.top == S.base)
{
return ERROR;
}
else
{
e = *(S.top-1);
return OK;
}
}
Status Push(SqStack &S, ElemType e) //把元素压入栈顶
{
if(S.top - S.base >= S.stacksize) //判断栈是否上溢
{
S.base = (ElemType *)realloc(S.base,sizeof(ElemType)*(STACKINCREMENT+S.stacksize));
if(!S.base) return OVERFLOW;
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
* S.top = e;
S.top++;
return OK;
}
Status Pop(SqStack &S, ElemType &e) //弹出栈首元素,并返回该值
{
if(S.base == S.top) return ERROR; //是否下溢
e = *(--S.top);
return OK;
}
链栈的实现代码如下:
#include <iostream>
using namespace std;
#include <malloc.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int ElemType;
typedef int Status;
typedef struct stack{
ElemType data;
struct stack *next;
}lkstack, *linkstack;
Status CreateStack(linkstack &S) //创建链栈,需要使用头插法,使得头指针指向的是栈首
{
int len;
cout<<"请输入要创建的栈的长度:"<<endl;
cin>>len;
S = (linkstack)malloc(sizeof(lkstack));
S->next = NULL;
for(int i = 0; i < len; i++)
{
linkstack p = (linkstack)malloc(sizeof(lkstack));
cout<<"输入元素值"<<endl;
cin>>p->data;
p->next = S->next;
S->next = p;
}
linkstack q = S->next;
while(q)
{
cout<<"值为:"<<q->data<<endl;
q = q->next;
}
}
Status DestroyStack(linkstack &S) //销毁栈
{
linkstack p, q;
p = S;
q = S->next;
while(q)
{
free(p);
p = q;
if(!q->next)
{
free(q);
break;
}
q = q->next;
}
cout<<"销毁成功"<<endl;
return OK;
}
Status EmptyStack(linkstack S)
{
if(!S->next) return TRUE;
return FALSE;
}
Status Push(linkstack &S)
{
ElemType e;
linkstack p = (linkstack)malloc(sizeof(lkstack));
cout<<"请输入新插入的值"<<endl;
cin>>e;
p->data = e;
p->next = S->next;
S->next = p;
linkstack q = S->next;
while(q)
{
cout<<"值为:"<<q->data<<endl;
q = q->next;
}
return OK;
}
Status Pop(linkstack &S, ElemType &e)
{
linkstack p = S->next;
e = S->next->data;
S->next = S->next->next;
free(p);
linkstack q = S->next;
while(q)
{
cout<<"值为:"<<q->data<<endl;
q = q->next;
}
return OK;
}
二.
队列也是一种特殊的线性表。特点是:先进先出(FIFO),先进队列的元素先出队列,后进队列的元素后出。基本操作:队列的初始化、判断队列空、入队列、出队列等。队列很好理解,就比如在学校里面打饭,谁排在前面,谁就先打好饭离开,后来的就到队尾。
队列也有两种存储形式:数组和链表。
数组队列也存在上溢和下溢问题,和数组栈一样的意思。队列的插入操作在队尾进行,删除操作在队首进行,这与栈不同,栈的插入和删除操作都在栈首进行。
数组队列实现代码如下:
#include <iostream>
using namespace std;
#include <malloc.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define MAXSIZE 100
typedef int ElemType;
typedef int Status;
typedef struct queue
{
ElemType *head;
ElemType *tail;
int headsize;
int tailsize;
}arrayQueue;
Status CreateQueue(arrayQueue &Q)
{
Q.tail = (ElemType *)malloc(sizeof(ElemType)*MAXSIZE);
memset(Q.tail, 0, sizeof(Q.tail));
Q.tail = Q.tail + 20;
Q.head = Q.tail;
Q.tailsize = 21;
Q.headsize = 78;
return OK;
}
Status EnQueue(arrayQueue &Q)
{
ElemType e;
cout<<"请输入要插入的值"<<endl;
cin>>e;
if(!Q.tailsize) //判断是否上溢
{
cout<<"队列已满"<<endl;
}
else
{
*Q.tail = e;
Q.tail--;
Q.tailsize--;
}
}
Status EmptyQueue(arrayQueue Q)
{
if(Q.tail == Q.head)
return TRUE;
return FALSE;
}
Status DeQueue(arrayQueue &Q, ElemType &e)
{
if(EmptyQueue(Q)) //判断是否下溢
return ERROR;
e = *Q.head;
Q.head--;
Q.headsize++;
return OK;
}
链表队列的实现后面补上。
栈的删除和插入只能在同一端进行,队列的删除和插入操作在两端进行。需要注意的是,有种比较特殊的队列,叫双端队列,插入和删除操作都可以在两端进行,既可以当成栈用,也可以当成队列用。在后面的博客会详细介绍。