栈和队列在逻辑上属于线性表的范畴,只是运算受到了严格的限制,称它们为运算受限的线性表。
一,栈
栈是限定仅在表尾进行插入和删除运算的线性表。我们把表尾称为栈顶(TOP),表头称为栈底。当栈中没有元素时称为空栈。入栈是指在栈顶插入数据元素,出栈是指在栈顶删除数据元素。
对于栈来说,最后进栈的元素,最先出栈,故把栈称为后进先出的数据结构,或先进后出。
栈的用途:汇编处理程序中的句法识别,表达式计算,回溯问题,在函数调用时的参数传递和函数值的返回。
1,栈的顺序存储表示--顺序栈
用数组来存储。由于栈底是固定不变的,而栈顶是随进栈出栈操作动态变化的,因此为了实现对栈的操作,必须记住栈顶的当前位置。另外,栈是有容量限制的。
struct Stack
{
datatype elements[maxsize];
int Top; //表示当前栈顶位置
};
置空栈时设S->top=-1;
注意出栈时的操作:
datatype *Pops(struct Stack *S){
S->top--;
ret=(datatype *)malloc(sizeof(datatype));
*ret=S->elements[S->top+1];
return ret;
} //如果返回值是整型的话就没必要这么做
多个栈共享存储空间:
两个栈共享存储空间时,将两个栈的栈底设在存储空间的两端,让两个栈的栈顶各自向中间延伸。
2,栈的链式存储表示--链栈
top是栈顶指针,它唯一的确定一个链栈。当top等于NULL时,该链栈为空栈。
struct Node{
datatype element;
struct Node *next;
};
struct Node *top;
入栈操作:
struct Node *push(struct Node *top,datatype e)
{
struct Node *p;
p=(struct Node *)malloc(sizeof(struct Node));
p->element=e;
p->next=top;
top=p;
return top;
}
3,栈的应用
(过程递归调用)
要正确实现程序的递归调用,必须解决参数的传递和返回地址问题。进行调用时,每递归一次,都要给所有参变量重新分配存储空间,并要把前一次调用的实参和本次调用后的返回地址保留。递归结束时要逐层释放这些参数所占的存储空间,并按后调用先返回的原则返回各层相应的返点。
实现这种存储分配和管理最有效的工具是栈。
(地图染色问题--“回溯问题”)
算法的基本思想是:从行政区1开始染色,每个区域用所有颜色依次试验,若当前颜色与周围颜色都不重色,则用栈记下该区域颜色序号;否则依次用下一个颜色进行试探。若出现所有颜色均与相邻区域的颜色重色,则必须退栈回溯,修改当前栈顶的颜色序号,再进行试探。
在计算机实现上述算法时,用一个关系矩阵R[N][N]来描述各行政区域间的相邻关系。除关系矩阵外,还需要设置一个栈S,用来记录行政区域的所染颜色的序号S[i]=k; k表示