目录
1. 栈
后进先出 LIFO 先进后出 FILO
- Top:栈顶
- Base:栈底
- PUSH:插入元素到栈顶,即入栈
- POP:从栈顶删除最后一个元素,即出栈
1.1 顺序存储:顺序栈
顺序栈的表示:
#define MAXSIZE 100
typedef struct{
SElemType *base; //栈底
SElemType *top; //栈顶
int stacksize; //栈可用最大容量
}SqStack;
初始化:
Status InitStack(SqStack &S){ //创建一个空栈
S.base = (SElemType*)malloc(sizeof(SElemType));
if(!S.base)exit(OVERFLOW); //存储分配失败
S.top = S.base; //栈顶指针 等于 栈底指针
S.stacksize = MAXSIZE;
return OK;
}
判断栈是否为空:
Status StackEmpty(SqStack S){ // 若栈为空 返回TRUE
if(S.top == S.base)
return TRUE;
else
return FALSE;
}
求长度:
int StackLength(SqStack S){
return S.top-S.base;
}
清空栈:
Status ClearStack(SqStack S){
if(S.base) S.top = S.base;
return OK;
}
销毁栈:
Status DestroyStack(SqStack &S){
if(S.base){
delete S.base;
S.base =S.top =NULL;
S.stacksize =0;
}
return OK;
}
入栈:
- 判断是否栈满,满了返回ERROR
- 元素e压入栈顶
- 栈顶指针加一
Status push(SqStack &S,SElemType e){
if(S.top-S.base==stacksize) return ERROR; //栈满
*S.top ++=e;//* 对所指空间的操作 ||对指针所指的值的直接操作
return OK;
}
出栈:
- 判断是否栈空,空了返回ERROR
- 获取栈顶元素e
- 栈顶指针减一
Status Pop(SqStack &S,SElemType &e){
if(S.top==S.base) return ERROR;
e = *-- S.top;
return OK;
}
1.2 链式存储:链栈
链栈的表示:
typedef struct StackNode{
SELemType data;
struct StackNode *next;
}StackNode, *LinkStack;
LinkStack S; //尾指针
初始化:
void InitStack(LinkStack &S){
//构建一个空栈 头指针为空
S=NULL;
return OK;
}
判断是否为空:
Status StackEmpty(LinkStack S){
if(S==NULL)return TRUE;
else return FALSE;
}
获取栈顶元素:
SElemType GetTop(LinkStack S){
if(S!=NULL)
return S->data;
}
入栈:
Status Push(SqStack &S,SElemtype e){
p = (LinkStack)malloc(sizeof(StackNode));
p->data =e; //新节点数据域 置为e
p->next =S;// 将新节点插入栈顶
S=p;//修改栈顶指针
return OK;
}
出栈:
Status Pop(LinkStack &S,SElemType &e){
if(S==NULL) return ERROR;
//S->next =S->next->next;
e = S->data;
p = S;
S = S->next;
delete p;
return OK;
}
1.3 栈与递归
递归问题:
阶乘
int fact(int n){
if(n==1) return 1;
else return n*fact(n-1);
}
Fibonacci数列
int fib(int n){
int fn;
if(n==0) fn=0;
else if(n==1) fn=1;
else fn=fib(n-1)+fib(n-2);
return fn;
}
Ackerman函数
int ack(int m,int n){
while(m!=0){
if(n==0) n=1;
else n=ack(m, n-1);
m--;
}
return n+1;
}
Hanoi塔:
void move(int n, char* x, char* z)
{
printf("将编号为%d的圆盘从%s移动到%s\n ", n, x, z);
}
void hanoi(int n, char* x, char* y, char* z)
{
if (n == 1)
{
move(1, x, z); //将编号为1的圆盘从x移动到z
}
else
{
hanoi(n - 1, x, z, y); //将编号为n-1的圆盘从x移动到y,z作为辅助盘
move(n, x, z); //将编号为n的圆盘从x移动到z
hanoi(n - 1, y, x, z); //将编号为n-1的圆盘从y移动到z,x作为辅助盘
}
}
int main()
{
int n = 3;
char* a = "1号";
char* b = "2号";
char* c = "3号";
hanoi(n, a, b, c);
return 0;
}
2. 队列
先进先出 FIFO,一端(队尾rear)插入,另一端(队头front)删除
2.1 顺序存储:循环队列
判断空满:
1. 计数器,计数变量最大时为队满,为零时则队空;
2. 设立标志位来区别,入队true,出队false,
sq->rear=sq->front且标志位为true则队满,sq->rear=sq->front且标志位为false则队空;
3. 牺牲一个元素空间来区别,队头在队尾下一个位置,即sq->rear+1=sq->front则为队满;
2.2 链式存储:链队列
初始化:
Q->front->next=NULL;
Q->rear->next=NULL;
x入队:
px=new Qnode;
px->data=x;
px->next=NULL;
Q->rear->next=px;
Q->rear=px;
y入队:
px=new Qnode;
px->data=y;
px->next=NULL;
Q->rear->next=px;
Q->rear=px;
x出队:
px=Q->front->next;
Q->front->next=Q->front->next->next;
free(px);
y出队(最后一个元素):
px=Q->front->next;
Q->front->next=Q->front->next->next;
free(px);
Q->rear=Q->front;