文章目录
- 主要内容
- 一.栈基础练习题
- 总结
主要内容
- 栈基础练习题
一.栈基础练习题
1.设链表不带头结点且所有操作均在表头进行,则下列最不适合作为链栈的是 ( C )。
A.只有表头结点指针,没有表尾指针的双向循环链表
B.只有表尾结点指针,没有表头指针的双向循环链表
C.只有表头结点指针,没有表尾指针的单向循环链表
D.只有表尾结点指针,没有表头指针的单向循环链表
解析如下(示例):
对于双向循环链表,不管是表头指针还是表尾指针,都可以很方便地找到表头结点,方便在表头做插入或删除操作。
而单循环链表通过尾指针可以很方便地找到表头结点,但通过头指针找尾结点则需要遍历一次链表。
对于 C,插入和删除结点后,找尾结点需要花费 O(n的时间。
2.一个栈的入栈序列为 1,2,3,…,n,出栈序列是P1,P2,P3,…,Pn。若P2=3,则P3可能取值的个数是( C )
A.n-3
B.n-2
C.n-l
D.无法确定
解析如下(示例):
显然,3 之后的4,5...n 都是P3可取的数(持续进直到该入后立即出)。
接下来分析1和2:P1可以是3之前入的数 (可能是1或2),也可以是4,
当P=1时,P3可取2:当P=2时,P3可取1;当P=4时,P3可取除1,3,4之外的所有数;
故P可能取值的个数为n-1
3.假设以I和 0分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和 O组成的序列,可以操作的序列称为合法序列,否则称为非法序列。
1)下面所示的序列中哪些是合法的?
A.OIIOIOO
B.IOOIOIIO
C.IIIOIOIO
D.IIIOOIOO
2) 通过对 1)的分析,写出一个算法,判定所给的操作序列是否合法。若合法,返回true,否则返回 false(假定被判定的操作序列已存入一维数组中)。
代码如下(示例):
1)A、D合法,而B、C不合法。
在B 中,先入栈1次,再连续出栈2次,错误。
在C中,入栈和出栈次数不一致,会导致最终的栈不空。
A、D 均为合法序列。
注意:入栈次数一定大于等于出栈次数;结束时,栈一定为空。
2)设被判定的操作序列已存入一维数组 A 中。
算法的基本设计思想:依次逐一扫描入栈出找序列(即由“I”和“O”组成的字符串),
每扫描至任一位置均需检查出栈次数(即“O”的个数)是否小于入栈次数(“I”的个数,若大于则为非法序列。
扫描结束后,再判断入栈和出栈次数是否相等,若不相等则不合题意,为非法序列。
int Judge(char Al ]){
//判断字符数组A中的输入输出序列是否是合法序列。如是,返回true,否则返回false
int i=0;
int j=k=0; //i为下标,i和k分别为字母I和O的个数
while(A[i]!='\0'){ //未到字符数组尾
switch(A[i]){
case 'I':j++; break; //入栈次数增1
case 'O': k++;
if(k>j){printf("序列非法\n");exit(0);}
}
i++; //不论A[i]是“I”或“o”,指针均后移
} //while
if(j!=k){
printf("序列非法\n");
return false;
}
else{
printf("序列合法\n");
return true;
}
}
[另解]入栈后,栈内元素个数加 1:出栈后,栈内元素个数减 1,
因此可将判定一组出入栈序列是否合法转化为一组由+1、-1组成的序列,
它的任意前缀子序列的累加和不小于0(每次出栈或入栈操作后判断)则合法;否则非法。
4.设单链表的表头指针为L,结点结构由 data 和 next 两个域构成,其中 data 域为字符型。试设计算法判断该链表的全部 n 个字符是否中心对称。例如 xyx、xyyx 都是中心对称。
代码如下(示例):
算法思想:使用核米判断链表中的数据是否中心对称。让链表的前一半元素依次进栈。
在处理链表的后一半元素时,当访问到链表的一个元素后,就从栈中弹出一个元素,两个元素比较,
若相等,则将链表中的下一个元素与栈中再弹出的元素比较,直至链表到尾。
这时若栈是空栈,则得出链表中心对称的结论;
否则,当链表中的一个元素与栈中弹出元素不等时,结论为链表非中心对称,结束算法的执行。
int dc(LinkList L,int n){
// 是带头结点的n个元素单链表,本算法判断链表是否是中心对称
int i;
char s[n/2]; //s字符栈
p=L->next; //p是链表的工作指针,指向待处理的当前元素
for(i=0;i<n/2;i++){ //链表前一半元素进栈
s[i]=p->data;
p=p->next;
}
i--; //恢复最后的i值
if(n%2==1) //若n 是奇数,后移过中心结点
p=p->next;
while(p!-NULL&&s[il==p->data){ //检测是否中心对称
i--; //i 充当栈顶指针
p=p->next;
}
if(i==-1) //栈为空栈
return 1; //链表中心对称
else
return 0; //链表不中心对称
}
算法先将“链表的前一半”元素(字符)进栈。当n为偶数时,前一半和后一半的个数相同;
当n为奇数时,链表中心结点字符不必比较,移动链表指针到下一字符开始比较。
比较过程中遇到不相等时,立即退出 while循环,不再进行比较。
本题也可以先将单链表中的元素全部入栈,然后扫描单链表 L 并比较,直到比较到单链表L尾为止,
但算法需要两次扫描单链表 L,效率不及上述算法高。
总结
以上是今天要讲的内容,练习了线性表–栈相关练习题。