第3章栈和队列
本章的基本内容是:
特殊的线性表——栈、队列
¾从数据结构角度看,栈和队列是操作受限的线性表,他们的逻辑结构相同。
栈的逻辑结构
栈:限定仅在表尾进行插入和删除操作的线性表。
空栈:不含任何数据元素的栈。
允许插入和删除的一端称为栈顶,另一端称为栈底。
栈的操作特性:后进先出(LIFO) 栈的逻辑结构
栈的抽象数据类型定义
ADT Stack
Data
栈中元素具有相同类型及后进先出特性,相邻元素具有前驱和后继关系
Operation
InitStack
前置条件:栈不存在输入:无功能:栈的初始化输出:无后置条件:构造一个空栈
栈的抽象数据类型定义
DestroyStack
前置条件:栈已存在输入:无功能:销毁栈输出:无
后置条件:释放栈所占用的存储空间
Push
前置条件:栈已存在输入:元素值x 功能:在栈顶插入一个元素x 输出:如果插入不成功,抛出异常后置条件:如果插入成功,栈顶增加了一个元素
栈的抽象数据类型定义
Pop
前置条件:栈已存在输入:无功能:删除栈顶元素输出:如果删除成功,返回被删元素值,否则,抛出异常后置条件:如果删除成功,栈减少了一个元素
GetTop
前置条件:栈已存在输入:无功能:读取当前的栈顶元素输出:若栈不空,返回当前的栈顶元素值后置条件:栈不变
栈的抽象数据类型定义
Empty
前置条件:栈已存在输入:无功能:判断栈是否为空
输出:如果栈为空,返回1,否则,返回0 后置条件:栈不变 endADT
栈的顺序存储结构及实现栈的顺序存储结构—
顺序栈类的声明
{ public:
SeqStack ( ){top=-1; } ; ~SeqStack ( ); void Push ( T
x );
T Pop ( );
T
GetTop ( ) {if (top!=-1) return
data[top];}
bool Empty ( ) { if(top==-1) return
1; else return 0;}
private:
T
data[StackSize]; int top;
}
顺序栈的实现——入栈
操作接口: void Push( T
x ); template void
SeqStack::Push ( T x)
{ if (top==StackSize-1) throw “溢出”; top++;
data[top]=x;
}
两栈共享空间
两栈共享空间:使用一个数组来存储两个栈,让一个栈的栈底为该数组的始端,另一个栈的栈底为该数组的末端,两个栈从各自的端点向中间延伸。
~BothStack( );
void Push(int i, T x); T Pop(int i);
T GetTop(int i); bool Empty(int i); private:
T
data[StackSize];
int top1, top2;
};
两栈共享空间的实现——插入操作接口:void Push(int i, T x) ;
-
如果栈满,则抛出上溢异常;
-
判断是插在栈1还是栈2;
2.1 若在栈1插入,则
2.1.1 top1加1;
2.1.2 在top1处填入x;
2.2 若在栈2插入,则
2.2.1 top2减1;
2.2.2 在top2处填入x;两栈共享空间的实现——插入操作接口:void
Push(int i, T x) ;
template
void BothStack::Push(int i, T x )
{
if (top1top2-1) throw “上溢”;
if (i1) data[++top1]=x;
if (i==2) data[--top2]=x;
}
两栈共享空间的实现——删除操作接口:T Pop(int i) ;
- 若是在栈1删除,则
1.1 若栈1为空栈,抛出下溢异常;
1.2 删除并返回栈1的栈顶元素;
- 若是在栈2删除,则
2.1 若栈2为空栈,抛出下溢异常;
2.2 删除并返回栈2的栈顶元素;两栈共享空间的实现——删除操作接口:T Pop(int i) ;
T BothStack::Pop(int i)
{
if (i==1) //将栈1的栈顶元素出栈
{ if (top1== -1) throw “下溢”;
return data[top1–]; }
if (i==2) //将栈2的栈顶元素出栈
{ if (top2==StackSize) throw “下溢”;
return data[top2++]; }
} 两栈共享空间的实现——读取栈i当前的栈顶元素操作接口:T
GetTop(int i); template
T BothStack::GetTop(int i)
{ if(i==1)
{ if (top1!=-1) return data[top1]; }
if(i==2)
{ if(top2!=StackSize) return data[top2]; } } 两栈共享空间的实现——判断栈i是否为空栈操作接口: bool Empty(int i) ; template
bool BothStack::Empty(int i)
{
if(i==1)
{ if(top1==-1) return
1; else return 0; } if(i==2)
{
if(top2==StackSize) return 1; else return 0; }
}
空间性能:
¾顺序栈:有元素个数的限制和空间浪费的问题。 ¾链栈:没有栈满的问题,只有当内存没有可用空间时才会出现栈满,但是每个元素都需要一个指针域,从而产生了结构性开销。
总之,当栈的使用过程中元素个数变化较大时,用链栈是适宜的,反之,应该采用顺序栈。
1
递归的定义
子程序(或函数)直接调用自己或通过一系列调用语句间接调用自己,是一种描述问题和解决问题的基本方法。
2
递归的基本思想
问题分解:把一个不能或不好解决的大问题转化为一个或几个小问题,再把这些小问题进一步分解成更小的小问题,直至每个小问题都可以直接解决。
3
递归的要素
⑴
递归边界条件:确定递归到何时终止,也称为递归出口;
⑵
递归模式:大问题是如何分解为小问题的,也称为递归体。