目录
栈(FIFO)
栈的分类
栈的相关介绍
栈的相关操作
顺序栈
代码
共享栈
存储结构
链栈
存储结构
王道考研课后习题题解
栈主要分成三大类
栈是先进先出的数据结构,区别于链表无论什么地方都可以插入删除,栈只能由栈顶压入,栈顶弹出。
深度搜索就是借用栈进行操作的,具体到搜索再说。
插入push() | 删除 pop() | 遍历输出 display() |
取栈顶元素 top() | 计算栈长 size() | |
判空 empty() | 链栈合并栈 combine() |
操作待补充
最普通的栈。开辟规定的栈空间,将数据插入。
2019-9-16 第一次更新,本次更新增加c++面向对象的源代码。
#include
#define MAXSIZE 50
using namespace std;
class Stack{
private:
int data[MAXSIZE];
int top;
public:
Stack(){
top = -1;
}
void SetTop(int top){
top = top;
}
int *GetData(){
return data;
}
int GetNext(){
return top;
}
void Push(int value){
data[++top] = value;
}
int GetTop(){
return data[top];
}
int Pop(){
int pop = GetTop();
top--;
return pop;
}
int GetSize(){
return top;
}
};
int main(){
Stack *s = new Stack();
for(int i = 1 ; i< 5 ; i ++){
s[0].Push(i);
}
for(int i = 1 ; i< 5 ; i ++ ){
cout<
c语言版本,也就是跟着严蔚敏版数据结构写的源代码。(我个人不太喜欢用c语言,因为不能使用stl库,如果知道c语言实现哈夫曼树有多麻烦,而c++使用哈夫曼树多么容易后就不会再喜欢c语言了)
#include
#include
#include
#define maxlen 150
//顺序栈存储结构
typedef struct{
int data[maxlen]; //栈长
int top;
}sqstack;
sqstack init(sqstack &S){
S.top = -1;
return S;
}
sqstack push(int interger ,sqstack &S){
if(S.top > maxlen-1){
printf("overflowed!\n");
return S;
}
S.top ++;
S.data[S.top] = interger;
return S;
}
int pop(sqstack &S){
int ans = S.data[S.top];
if(S.top <= -1){
S.top = -1;
printf("empty!\n");
return 0x3fff;
}
S.top --;
return ans;
}
bool empty(sqstack S){
if(S.top != -1) return true;
else return false;
}
int size(sqstack S){
return S.top+1;
}
void display(sqstack S){
for(int i = 0 ; i < S.top+1 ; i ++){
printf("%d ",S.data[i]);
}
printf("\n");
return;
}
int Top(sqstack S){
if(S.top == -1){
printf("empty!\n");
return 0x3fff;
}
return S.data[S.top];
}
int main(){
sqstack S;
init(S);
int i = 0 ,num[10]={0,1,2,3,4,5,6,7,8,9};
printf("%d\n",Top(S));
while(i<10){
push(num[i],S);
display(S);
i ++;
}
printf("%d\n",Top(S));
while(i>=-1){
//pop(S);
printf("%d\n",pop(S));
//display(S);
i--;
}
}
共享栈实质上是将两个栈合并,初始化时一个栈顶指针指向-1,另一个栈顶指针指向最大长度。然后就是顺序栈的常规操作
typedef struct{
int data[maxlen];
int top1=-1,top2=maxlen;
}sharestack;
操作和顺序栈差不多,我就举一个压入左栈和压入右栈的例子,这个操作其实也是20版王道考研66页第五题。
不过他是将一个栈拆分成两个单独的栈。操作上有些许不同。
sharestack push_left(int target,sharestack Ss){
if(Ss.top1 < Ss.top2){
Ss.top1 ++;
Ss.date[Ss.top1] = target;
retrun Ss;
}
printf("overflowed!\n");
}
sharestack push_right(int target,sharestack Ss){
if(Ss.top1 < Ss.top2){
Ss.top2 --;
Ss.date[Ss.top2] = target;
retrun Ss;
}
printf("overflowed!\n");
}
int pop_left(sharestack Ss){
int ans;
if(Ss.top1 <= -1){
Ss.top = -1;
printf("empty!\n");
return 0x3fff;
}
Ss.top1 --;
return ans;
}
int pop_right(sharestack Ss){
int ans;
if(Ss.top2 >= maxlen){
Ss.top = maxlen;
printf("empty!\n");
return 0x3fff;
}
Ss.top2 ++;
return ans;
}
链栈采用的是链表形式,所以不再赘述,给出链栈的存储结构,但是需要注意还有头节点的链栈和无头节点的链栈在具体操作上有些许不同。
//链栈存储结构
/**
链栈使用单链表存储数据,使用头插法插入数据,每次出栈都是删除第一个数据节点
和单链表类似,不再赘述
*/
typedef struct Snode{
int value;
struct Snode *next;
}stack,*linkstack;
Q3.2:判断操作序列是否合法
Ans:
使用count记录当前栈内元素数量,遍历字符串时,如果遇到I,count ++,否则{ count --,判断count 是否小于0,小于0则非法},循环结束返回true
Q4:判断链表内存放的数据是否为回文字符
Ans:
计算链表长度n,取n/2放入栈内,从n/2开始,每到一个节点与栈顶比较,如果一致继续循环,否则返回false,循环结束返回true,需要注意的是,如果n为奇数时,需要从n/2+1开始比较。
Q5:共享栈的入栈出栈操作
Ans:
共享栈需要注意,入栈是否会上溢,出栈是否会下溢。共享栈有多个栈,故入栈操作有入栈元素和栈号两个参数,而出栈操作有栈号一个参数。入栈前需要判断 top1+1是否等于top2 是则上溢,出栈前如果top1<=0或者top2>=n 则下溢。