• 数据结构与算法分析


    1.描述:实质是一种受到限制的表,即插入删除只能在表的末端,能够实现LIFO(后进先出)

    2.栈的实现

      链表实现(链栈)

      数组实现(顺序栈)

    3.链栈

    创建一个空栈

     1 struct Node 
     2 {
     3     int value;
     4     Node *next;
     5 };
     6 
     7 //创建了一个头节点为S的链栈,S将一直表示栈顶元素
     8 Node *CreatStack()
     9 {
    10     Node *S = new Node;
    11     S->next = NULL;
    12     return S;
    13 }

    测试栈是否为空

    1 int IsEmpty(Node *S)
    2 {
    3     return S->next == NULL;
    4 }

    从栈顶弹出元素

     1 void Pop(Node *S)
     2 {
     3     Node *FirstCell;
     4     if (IsEmpty(S))                  //空栈,将返回异常
     5         cout << "Empty Stack" << endl;
     6     else
     7     {
     8         FirstCell = S->next;            //取出栈顶
     9         S->next = S->next->next;          //使S指向新的栈顶
    10         delete FirstCell;              //删除原栈顶,完成出栈
    11     }
    12 }

    返回栈顶元素(不弹出,不改变栈顶指针),遇到空栈将返回异常

    1 int Top(Node *S)
    2 {
    3     if (!IsEmpty(S))
    4         return S->next->value;
    5 }

    清空栈(同时销毁物理内存)

    1 void MakeEmpty(Node *S)
    2 {
    3     while (!IsEmpty(S))
    4         Pop(S);
    5 }

    压栈

     1 void Push(int x, Node *S)
     2 {
     3     Node *TempCell = new Node;
     4     if (TempCell == NULL)
     5         cout << "Out of space" << endl;
     6     else
     7     {
     8         TempCell->value = x;          //把x赋值给value
     9         TempCell->next = S->next;        //将新节点设为栈顶
    10         S->next = TempCell;           //使S指向新的栈顶
    11     }
    12 }

    遍历栈

    1 void Print(Node *S)
    2 {
    3     Node *p = S->next;        //将p初始化为栈顶
    4     while (p != NULL)
    5     {
    6         cout << p->value << endl;
    7         p = p->next;
    8     }
    9 }

    注意,内存分配操作的时间开销较大(C的malloc和free,C++的new和delete),可用通过建立第二个栈来避免,第一个栈中的元素弹出时将不会被删除,而是暂时存放在第二个栈中,然后当第一个栈需要新的元素时,将首先在第二个栈中查找,由于在链栈中,所有的操作均花费常数时间,所以检索第二个栈的开销相对于内存分配是值得的。

    声明一个Stack链表

    1 struct Stack 
    2 {
    3     Node *top;        //top指向栈顶
    4     Node *bottom;      //bottom指向栈底
    5 };

    这样在任意Node处都可以通过p->top或者p->bottom的方式获得当前栈的栈顶和栈底

    判断栈是否为空也可以这样进行 

    1 int IsEmpty(Node *p)
    2 {
    3     if (p->top == p->bottom)     //栈顶和栈底相同
    4         return 1;
    5     else
    6         return 0;
    7 }

    4.顺序栈

    数组实现的顺序栈避免了使用指针,顺序栈使用一个一维数组来存放栈的元素

    每一个栈有一个TopOfStack,对于空栈来说TopOfStack = -1

    压栈时,将TopOfStack加1,Stack[TopOfStack] = x;出栈时,减1

    1 typedef struct StackRecord 
    2 {
    3     int capacity;    //栈大小
    4     int TopOfStack;     //栈顶
    5     int *Array;         //数组地址
    6 }Stack;

    对空栈的pop和满栈的push都将引起程序崩溃

    创建栈,数组实现

     创建空栈

    1 void MakeEmpty(Stack *S)
    2 {
    3     S->TopOfStack = -1;
    4 }

    创建栈(不考虑内存申请失败)

    1 Stack* CreatStack(int MaxSize)
    2 {
    3     StackRecord *S = new StackRecord;
    4     S->Array = new int[MaxSize];
    5     S->capacity = MaxSize;
    6     MakeEmpty(S);
    7     return S;
    8 }

     检测是否为空栈

    1 int IsEmpty(Stack *S)
    2 {
    3     return S->TopOfStack == -1;
    4 }

    检测是否为满栈

    1 int IsFull(Stack *S)
    2 {
    3     return S->TopOfStack == MaxSize - 1;
    4 }

    进栈

    1 void Push(int x, Stack *S)
    2 {
    3     if (IsFull(S))              //栈满将抛出异常
    4         ;
    5     else
    6         S->Array[++S->TopOfStack] = x;
    7   //S->TopOfStack++;
    8 //S->Array[
    TopOfStack] = x;
    9 }

    返回栈顶元素

    1 int Top(Stack *S)
    2 {
    3     if (!IsEmpty(S))
    4         return S->Array[S->TopOfStack];
    5     else
    6         ;
    7 }

    出栈

    1 void Pop(Stack *S)
    2 {
    3     if (IsEmpty(S))
    4         ;
    5     else
    6         S->TopOfStack--;
    7 }

    栈的遍历

    以遍历数组的方式遍历即可

    释放栈

    1 void DisposeStack(Stack *S)
    2 {
    3     if (S != NULL)
    4     {
    5         delete S->Array;
    6         delete S;
    7     }
    8 }

    5.链栈与顺序栈

    顺序栈比链栈操作简便,避免了指针,但对存储空间利用效率低,大小固定,不如链表实现灵活

    数组实现时,声明的栈太小,会造成栈溢出,太大则造成空间浪费

    6.栈的应用

    数据结构应用 - 栈

    参考资料:《数据结构与算法分析——C语言描述》    Mark Allen Weiss 

  • 相关阅读:
    COM编程-注册DLL形式的COM服务器
    控制台console使用MFC库函数,Cout输出CString的方法
    [C#]窗体切换--避免开启多个线程
    OpenCV配置使用版
    Dependency Walker使用说明
    TCP粘包和半包的处理方法
    GENERATED_UCLASS_BODY 和 GENERATED_BODY 区别
    c++ 的 坑真多之头文件
    Introduction to replication 翻译
    c++ 的 static_cast
  • 原文地址:https://www.cnblogs.com/CofJus/p/10202451.html
Copyright © 2020-2023  润新知