数据结构— —栈的基本操作(顺序栈和链栈)

简介: 数据结构— —栈的基本操作(顺序栈和链栈)

🎯目的:

1、掌握栈的顺序表示和实现。

2、掌握栈的链式表示和实现。


🎯内容:

1、栈的顺序表示和实现。

2、栈的链式表示和实现。


🎯环境:

TC或VC++。


🎯顺序栈步骤:

🎐1.栈的顺序表示和实现

编写一个程序实现顺序栈的各种基本运算,并在此基础上设计一个主程序,完成如下功能:


  1. 1初始化顺序栈


  1. 2插入元素


  1. 3删除栈顶元素


  1. 4取栈顶元素


  1. 5遍历顺序栈


  1. 6置空顺序栈


🎆注意要点:

顺序栈,入栈时需判断栈是否为满,栈满时不能入栈,否则出现空间溢出;出栈时需判断栈是否为空,为空时不能操作,否则产生错误;取栈顶元素与遍历之前也要判断栈是否为空。

typedef struct {
 
       SElemType *base;//栈底指针
 
       SElemType *top;//栈顶指针
 
       int stacksize;//栈可用的最大容量
 
} SqStack;

🎯顺序栈完整代码:

//顺序栈
#include "iostream"
using namespace std;
#define MAXSIZE 100
#define OK 1
#define ERROR 0;
#define OVERFLOW -1
typedef int Status;
typedef char SElemType ;
typedef struct{//定义顺序栈 
  SElemType *base;
  SElemType *top;
  int stacksize;
}SqStack;
Status InitStack(SqStack &S){//顺序栈的初始化 
  S.base=new SElemType [MAXSIZE];
  if(!S.base)
  exit(OVERFLOW);
  S.top=S.base;
  S.stacksize=MAXSIZE;
  return OK; 
}
Status Push(SqStack &S,SElemType e){//顺序栈的入栈 
  if(S.top-S.base==S.stacksize)
  return ERROR;
  *S.top++=e;
  return OK;
}
Status Pop(SqStack &S,SElemType &e){//顺序表的出栈 
  if(S.top==S.base)
    return OK;
  e=*--S.top;
  return OK;
}
SElemType GetTop(SqStack S){//取栈顶元素 
  if(S.base!=S.top)
    return *(S.top-1);
}
void StackTraverse(SqStack S){//遍历顺序栈 
  SElemType *p;
  p=S.top;
  cout<<"顺序栈的元素为:";
  while(p!=S.base){
    p--;
    printf("%2c ",*p);
  }
  cout<<endl;
} 
void CleanStack(SqStack &S){//置空栈 
  if(S.base)
  {
    S.top=S.base;
    cout<<"恭喜您,栈已清空"<<endl; 
  }
  else
  cout<<"栈不存在"<<endl;
}
bool isValid(char op[]){
  SqStack T;
  InitStack(T);//初始化 
  int i=0;
  while(op[i]!='\0'){
    if(op[i]=='I')
      Push(T,op[i]);
    else if(op[i]=='O'){
      char c;
      if(Pop(T,c)!=OK||c!='I')
        return false; 
    }
    i++;
  }
  if(T.top==T.base)
    return true;
  else
    return false;
} 
int main(){
  SqStack s;
  int choose=-1;
  SElemType e,n;
  cout<<"1.初始化顺序栈\n2.插入元素\n3.删除栈顶元素\n4.取栈顶元素\n5.遍历栈\n6.置空栈\n7.检验IO操作是否合法\n0.退出"<<endl;
  cout<<"提示:入栈时只能输入单个字符"<<endl; 
  cout<<"-----------------------------"<<endl;
  while(choose!=0){
    cout<<"请输入您的选择:";
    cin>>choose;
    switch(choose){
      case 1:
        if(InitStack(s)==1){
          cout<<"恭喜您初始化成功"<<endl;
        }
        else
          cout<<"很遗憾初始化失败"<<endl;
        break;
      case 2:
        cout<<"请输入您要插入的元素:";
        cin>>e;
        if(Push(s,e)==1)
          cout<<"恭喜您插入成功"<<endl;
        else
          cout<<"很遗憾插入失败"<<endl;
        break;
      case 3:
        if(Pop(s,e)==1){
          cout<<"恭喜您删除栈顶元素成功"<<endl;
          cout<<"删除的栈顶元素为:"<<e<<endl; 
        }
        else
          cout<<"很遗憾删除栈顶元素失败"<<endl;
        break;
      case 4:
        if(s.base==s.top)
          cout<<"您的栈已空"<<endl;
        else{
          n=GetTop(s);
          cout<<"栈顶元素为:"<<n<<endl;
         }
        break;
      case 5:
        if(s.base==s.top)
          cout<<"您的栈已空"<<endl;
        else{
          StackTraverse(s);
        }
        break;
      case 6:
        CleanStack(s);
        break;
      case 7:
        char op[MAXSIZE];
        cout<<"请输入要检验的序列";
        cin>>op;
        if(isValid(op))
          cout<<"输入的序列合法"<<endl;
        else
          cout<<"输入的序列不合法"<<endl; 
        break;
      case 0:
        cout<<"恭喜您已退出"<<endl;
        break;
      default:
        cout<<"输入错误,请您重新输入"<<endl; 
    }
  } 
  return 0;
}

🎯链栈步骤:

🎐2.栈的链式表示和实现

链栈的存储结构定义:

typedef struct StackNode {
 
       SElemType data;
 
       struct StackNode *next;
 
} StackNode, *LinkStack;


  1. 1链栈的初始化


  1. 2链栈的入栈


  1. 3链栈的出栈


  1. 4取链栈的栈顶元素


  1. 5遍历链栈


  1. 6置空链栈


🎆注意要点:

链栈,出栈时需判断栈是否为空,为空时不能操作,否则产生错误;取栈顶元素与遍历之前也要判断栈是否为空。


🎯链栈完整代码:

//链栈
#include "iostream"
using namespace std;
#define OK 1
#define OVERFLOW -1
#define ERROR 0
#define MAXSIZE 100
typedef int Status;
typedef char SElemType; 
typedef struct StackNode{//定义栈 
  SElemType data;
  struct StackNode *next;
}StackNode,*LinkStack;
Status InitStack(LinkStack &S){//链栈的初始化 
  S=NULL;
  return OK; 
}
Status Push(LinkStack &S,SElemType e){//入栈 
  LinkStack p;
  p=new StackNode;
  p->data=e;
  p->next=S;
  S=p;
  return OK;
}
Status Pop(LinkStack &S,SElemType &e){//出栈
  if(S==NULL)
    return ERROR;
  LinkStack p;
  e=S->data;
  p=S;
  S=S->next;
  delete p;
  return OK; 
}
SElemType GetTop(LinkStack S){//取栈顶元素
  if(S!=NULL)
    return S->data; 
}
void TraverseList(LinkStack S){//遍历链栈
  LinkStack p;
  p=S; 
  if(p){
    cout<<p->data<<endl;
    TraverseList(p->next);
  }
}
Status ClearStack(LinkStack &S){//置空链栈 
  LinkStack p;
  if(S=NULL)
    return ERROR;
  while(S!=NULL){
    p=S;
    S=S->next;
    delete p;
  }
    return OK;
}
bool isValid(char op[]){
  LinkStack T;
  InitStack(T);//初始化 
  int i=0;
  while(op[i]!='\0'){
    if(op[i]=='I')
      Push(T,op[i]);
    else if(op[i]=='O'){
      char c;
      if(Pop(T,c)!=OK||c!='I')
        return false; 
    }
    i++;
  }
  if(T==NULL)
    return true;
  else
    return false;
  } 
int main(){
  LinkStack s;
  SElemType e;
  int choose=-1;
  SElemType n;
  cout<<"1.链栈的初始化\n2.入栈\n3.出栈\n4.取栈顶元素\n5.遍历栈\n6.置空栈\n7.检验IO操作是否合法\n0.退出\n";
  cout<<"特别注意:入栈时只可以是单个字符!!!"<<endl;
  cout<<"----------------------------"<<endl;
  while(choose!=0){
    cout<<"请输入您的选择:";
    cin>>choose;
    switch(choose){
      case 1:
        if(InitStack(s)==1)
          cout<<"恭喜您初始化成功"<<endl;
        else
          cout<<"很遗憾初始化失败"<<endl;
        break;
      case 2:
        cout<<"请输入您要入栈的元素:";
        cin>>e; 
        if(Push(s,e)==1)
          cout<<"恭喜您入栈成功"<<endl;
        else
          cout<<"很遗憾入栈失败"<<endl;
        break;
      case 3:
        if(Pop(s,e)==1){
          cout<<"恭喜您出栈成功"<<endl;
          cout<<"出栈元素为:"<<e<<endl; 
        } 
        else
          cout<<"很遗憾出栈失败"<<endl;
        break;
      case 4:
        if(s==NULL)
          cout<<"您的栈已空"<<endl;
        else{
          n=GetTop(s);
          cout<<"栈顶元素为:"<<n<<endl;
         }
        break;
      case 5:
        if(s==NULL)
          cout<<"您的栈已空"<<endl;
        else{
          cout<<"链栈中的元素为:"<<endl;
          TraverseList(s);
        }
        break;
      case 6:
        if(ClearStack(s)==1)
          cout<<"恭喜您栈已置空"<<endl;
        else
          cout<<"很遗憾栈不存在"<<endl;
        break;
      case 7:
        char op[MAXSIZE];
        cout<<"请输入要检验的序列";
        cin>>op;
        if(isValid(op))
          cout<<"输入的序列合法"<<endl;
        else
          cout<<"输入的序列不合法"<<endl; 
        break;
      case 0:
        cout<<"恭喜您已退出"<<endl; 
          break;
      default:
        cout<<"输入错误,请重新输入"<<endl;
    }
  }
}

[附加题]

1、假设以I和O分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈的操作序、列可表示为仅由I和O组成的序列,称可以操作的序列为合法序列,否则称为非法序列。


下面所示的序列中哪些是合法的?


A. IOIIOIOO


B. IOOIOIIO


C. IIIOIOIO


D. IIIOOIOO


通过对以上序列的分析,写出一个算法,判定所给的操作序列是否合法。若合法,返回true,否则返回false (假定被判定的操作序列巳存入一维字符数组中)。


1. 顺序栈实现检验:

2.链栈实现检验:

相关文章
|
4月前
|
编译器 C语言 C++
栈区的非法访问导致的死循环(x64)
这段内容主要分析了一段C语言代码在VS2022中形成死循环的原因,涉及栈区内存布局和数组越界问题。代码中`arr[15]`越界访问,修改了变量`i`的值,导致`for`循环条件始终为真,形成死循环。原因是VS2022栈区从低地址到高地址分配内存,`arr`数组与`i`相邻,`arr[15]`恰好覆盖`i`的地址。而在VS2019中,栈区先分配高地址再分配低地址,因此相同代码表现不同。这说明编译器对栈区内存分配顺序的实现差异会导致程序行为不一致,需避免数组越界以确保代码健壮性。
52 0
栈区的非法访问导致的死循环(x64)
232.用栈实现队列,225. 用队列实现栈
在232题中,通过两个栈(`stIn`和`stOut`)模拟队列的先入先出(FIFO)行为。`push`操作将元素压入`stIn`,`pop`和`peek`操作则通过将`stIn`的元素转移到`stOut`来实现队列的顺序访问。 225题则是利用单个队列(`que`)模拟栈的后入先出(LIFO)特性。通过多次调整队列头部元素的位置,确保弹出顺序符合栈的要求。`top`操作直接返回队列尾部元素,`empty`判断队列是否为空。 两题均仅使用基础数据结构操作,展示了栈与队列之间的转换逻辑。
|
9月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
334 77
|
8月前
|
算法 调度 C++
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
167 11
|
8月前
|
DataX
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
|
9月前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
244 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
9月前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
141 9
|
9月前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
192 7
|
11月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
282 5
|
11月前
|
算法
数据结构之购物车系统(链表和栈)
本文介绍了基于链表和栈的购物车系统的设计与实现。该系统通过命令行界面提供商品管理、购物车查看、结算等功能,支持用户便捷地管理购物清单。核心代码定义了商品、购物车商品节点和购物车的数据结构,并实现了添加、删除商品、查看购物车内容及结算等操作。算法分析显示,系统在处理小规模购物车时表现良好,但在大规模购物车操作下可能存在性能瓶颈。
237 0