首页 > 其他分享 >数据结构学习记录(一)

数据结构学习记录(一)

时间:2023-08-19 23:44:37浏览次数:48  
标签:return struct 记录 队列 学习 int 堆栈 数据结构 Stack

堆栈与队列

一、知识要点

1、堆栈

  • 堆栈的定义

    • 堆栈(Stack)是一种具有一定约束的线性表,插入和删除操作都作用在一个称为栈顶(Top)的端点位置。
    • 通常把数据插入称为压入栈(Push),删除数据称为弹出栈(Pop)。在堆栈中,最后入栈的数据被最先弹出,所以堆栈也被称为后入先出
    • 堆栈的抽象数据类型定义:
      • 类型名称:堆栈(Stack)
      • 数据对象集:一个有0个或多个元素有穷线性表
      • 操作集:对于一个具体长度为正整数Maxsize的堆栈S,记堆栈中任一元素ElementType,堆栈的基本操作有:
        • Stack CreateStack(int MaxSize):生成空堆栈,其最大长度为MaxSize。
        • bool IsFull(Stack S) :判断堆栈S是否已满。满则返回true,否则返回false。
        • bool Push(Stack S, ElementType X):若S已满,则返回false,否则将元素X压入栈顶,返回true。
        • bool IsEmpty(Stack S):判断堆栈S是否为空,是则返回true,否则返回false。
        • ElementType Pop(Stack S):删除并返回栈顶元素。
  • 堆栈的实现

    • 栈的顺序储存实现

      #include<stdio.h>
      #include<string.h>
      #include<stdbool.h>
      #include<stdlib.h>
      #include<errno.h>
      //顺序栈的数据结构
      struct SNode
      {
          ElementType *Data;//存储元素的数组
          int Top;//栈顶指针
          int MaxSize;//堆栈最大容量
      };
      typedef struct SNode *Stack;
      
      //生成空堆栈
      Stack CreateStack(int MaxSize)
      {
          Stack S = (Stack)malloc(sizeof(struct SNode));//为堆栈开辟空间
          S->Data = (ElementType*)malloc(MaxSize * sizeof(ElementType));//给所有元素开辟空间
          S->Top = -1;
          S->MaxSize = MaxSize;
          return S;
      }
      
      //判断栈满
      bool IsFull(Stack S)
      {
          if(S->Top == S->MaxSize-1)
              return true;
          else
              return false;
      }
      
      //入栈
      bool Push(Stack S, ElementType X)
      {
          if(IsFull(S))
          {
              printf("堆栈满\n");
              return false;
          }
          else
          {
              S->Data[(S->Top)] = X;
              (S->Top)++;
              return true;
          }
      }
      
      //判断栈空
      bool IsEmpty(Stack S)
      {
          return (S->Top == -1)
      }
      
      //出栈
      ElementType Pop(Stack S)
      {
          if(IsEmpty(S))
          {
              printf("堆栈空\n");
             	return ERROR;
          }
          else
          {
              return (S->Data[S->Top]--)
          }
      }
      
    • 栈的链式储存结构

      #include<stdio.h>
      #include<string.h>
      #include<stdbool.h>
      #include<stdlib.h>
      #include<errno.h>
      
      //链式栈的数据结构
      typedef struct SNode *Stack;
      struct SNode
      {
          ElementType Data;
          Stack Next;
      };
      
      //创建堆栈的头节点
      Stack CreateStack()
      {
          Stack S;
          S = (Stack)malloc(sizeof(struct SNode));//给头节点分配空间
          S->Next = NULL;
          return S;
      }
      
      //判断堆栈空
      bool Empty(Stack S)
      {
          return (S->Next == NULL);
      }
      
      //入栈
      bool Push(Stack S, ElementType X)
      {
          //创建新节点,将新节点放在头节点后
          Stack TmpCell;
          TmpCell = (Stack)malloc(sizeof(struct SNode));//为新节点分配空间
          TmpCell->Data = X;
          TmpCell->Next = S->Next;
          S->Next = TmpCell;
          return true;
      }
      
      //出栈
      ElementType Pop(Stack S)
      {
          //返回栈顶元素并删除
          Stack FirstCell;
          ElementType TopCell;
          
          if(Empty(S))
          {
              printf("堆栈空\n");
              return ERROR;
          }
          else
          {
              FirstCell = S->Next;
              TopCell = FirstCell->Data;
              S->Next = FirstCell->Next;
              free(FirstCell);//释放栈顶元素内存
              return TopCell;
          }
      }
      

2、队列

  • 队列的定义

    • 队列(Queue)也是一个有序线性表,但队列的插入和删除操作是分别在线性表的两个不同端点同时进行的
    • 如果将元素A,B,C,D依次插入队列,那么第一个从队列删除的元素将是A,即先插入的将被率先删除,因此队列通常被称为先进先出表
    • 堆栈的抽象数据类型定义:
      • 类型名称:队列(Queue)
      • 数据对象集:一个有0个或多个元素有穷线性表
      • 操作集:对于一个具体长度为正整数Maxsize的队列S,记堆栈中任一元素ElementType,堆栈的基本操作有:
        • Queue CreateQueue(int MaxSize):生成空队列,其最大长度为MaxSize。
        • bool IsFull(Queue Q):判断队列Q是否已满,是则返回true,否则返回false。
        • bool AddQ(Queue Q, ElementType X):将元素X压入队列Q。若队列满返回false,否则返回true。
        • bool IsEmpty(Queue Q):判断队列Q是否为空。
        • ElementType DeleteQ(Queue Q):删除并返回队列头元素,若队列为空则返回错误信息。
  • 队列的实现

    • 队列的顺序储存实现

      //队列最简单的实现方法是用数组
      //要保证元素不会在数组溢出,就要把数组首尾相连
      #include<stdio.h>
      #include<string.h>
      #include<stdbool.h>
      #include<stdlib.h>
      #include<errno.h>
      
      //创建队列顺序数据结构
      struct QNode
      {
          ElementType* Data;	//存储元素的数组
          int Front, Rear;	//队列的头、尾指针
          int MaxSize;		//队列最大容量
      };
      typedef struct QNode *Queue;
      
      //创建空队列
      Queue CreateQueue(int MaxSize)
      {
          Queue Q = (Queue)malloc(sizeof(struct QNode));	//为队列赋予空间
          Q->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));		//为数组赋予空间
          Q->Front = Q->Rear = 0;
          Q->MaxSize = MaxSize;
          return Q;
      }
      
      //判断队列是否已满
      bool IsFull(Queue Q)
      {
          return ((Q->Rear + 1) % Q->MaxSize == Q->Front);
      }
      
      //压入队列
      bool AddQ(Queue Q, ElementType X)
      {
          if(IsFull(Q))
          {
              printf("队列满\n");
              return false;
          }
          else
          {
              Q->Rear = (Q->Rear + 1) % Q->MaxSize;
              Q->Data[Q->Rear] = X;
              return ture;
          }
      }
      
      //判断队列为空
      bool Empty(Queue Q)
      {
          return (Q->front == Q->Rear);
      }
      
      //返回并删除队列头元素
      ElementType DeleteQ(Queue Q)
      {
          if(Empty(Q))
          {
              printf("队列空\n");
              return ERROR;
          }
          else
          {
              Q->Front = (Q->Front + 1) % Q->MaxSize;
              return Q->Data[Q->Front];
          }
      }
      
    • 队列的链式储存实现

      //队列的头(front)必须指向链表的头节点,尾(rear)必须指向链表的尾节点
      //不能反过来,如果反过来,front就无法找到上一个节点
      
      #include<stdio.h>
      #include<string.h>
      #include<stdbool.h>
      #include<stdlib.h>
      #include<errno.h>
      
      //创建队列链式数据结构
      struct Node
      {
          ElementType Data;
          struct Node *Next;
      };
      typedef struct Node *Position;
      
      //创建队列的头尾指针
      struct QNode
      {
          Position Front, Rear;
      };
      typedef struct QNode *Queue;
      
      //创建空队列
      Queue CreateQueue()
      {
          Queue Q = (Queue)malloc(sizeof(struct QNode));
          Q->Front = Q->Rear = NULL;
          return Q;
      }
      
      //判断队列是否为空
      bool IsEmpty(Queue Q)
      {
          return (Q->Front == NULL);
      }
      
      //压入队列
      bool AddQ(Queue Q, ElementType X)
      {
          //创建新节点
          Position RearCell = (Position)malloc(sizeof(struct Node));
          RearCell->Data = X;
          RearCell->Next = NULL;
          //当队列为空时
          if(IsEmpty(Q))
          {
              Q->Front = Q->Rear = RearCell;
          }
          else
          {
              Q->Rear->Next = RearCell;
              Q->Rear = RearCell;
          }
          return true;
      }
      
      //弹出队列
      ElementType DeleteQ(Queue Q)
      {
          Position FrontCell;
          ElementType FrontElem;
          
          //当队列为空时,返回错误信息
          if(Empty(Q))
          {
              printf("队列空\n");
              return ERROR;
          }
          else
          {
              FrontCell = Q->Front;
              //当队列只有一个元素时
              if(Q->Front == Q->Rear)
              {
                  Q->Front = Q->Rear = NULL;
              }
              else
              {
                  Q->Front = Q->Front->Next;
              }
              FrontElem = FrontCell->Data;
              
              //释放节点内存
              free(FrontCell);
              return FrontElem;
          }
      }
      

3、应用实例

  • 多项式加法计算

  • #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <malloc.h>
    #include <stdlib.h>
    //比较函数
    int Compare(int a, int b);
    //置尾函数
    void Attach(int a, int b, Polynomial *p);
    
    //多项式加法运算
    
    //创建多项式数据类型
    struct PolyNode
    {
        //系数
        int coef;
        //指数
        int expon;
        //指向下一个节点的指针
        struct PolyNode *next;
    };
    typedef struct PolyNode *Polynomial;
    Polynomial p1, p2;
    
    //置尾函数
    void Attach(int a, int b, Polynomial p)
    {
        //创建多项式节点
        Polynomial P;
        //为新节点赋予内存和赋值
        P = (Polynomial)malloc(sizeof(struct PolyNode));
        P->coef = a;
        P->expon = b;
        P->next = NULL;
        p->next = P;
        p = P;
    }
    //多项式相加函数
    Polynomial PolyAdd(Polynomial p1, Polynomial p2)
    {
        //创建和多项式链表头节点和尾节点
        Polynomial front, rear, temp;
        //定义系数和变量
        int sum;
        //给头节点赋予内存
        front = (Polynomial)malloc(sizeof(struct PolyNode));
        rear = front;
        //当p1和p2都没加完时
        while (p1 != NULL && p2 != NULL)
        {
            //对p1指向节点的指数和p2的相比较
            switch(Compare(p1->expon, p2->expon))   //Compare函数需自己实现
            //当p1指向节点的指数大于p2时
            case 1:
                //将p1指向的节点放到和多项式链表表尾
                Attach(p1->coef, p1->expon, rear);
                //将p1向后移
                p1 = p1->next;
                break;
            //当p1指向节点的指数小于p2时
            case -1:
                //将p2指向的节点放到和多项式链表表尾
                Attach(p2->coef, p2->expon, rear);
                //将p2向后移
                p2 = p2->next;
                break;
            //当p1指向节点的指数等于于p2时
            case 0:
                //将p1和p2所指向节点的系数相加
                sum = p1->coef + p2->coef;
                //如果和不为0
                if (sum != 0)
                    Attach(sum, p1->expon, rear);
                //将p1和p2向后移
                p1 = p1->next;
                p2 = p2->next;
                break;
        }
        //如果某个多项式加完了,那么就将另一个多项式剩余的项放在和多项式后面
        if (p1 == NULL)
        {
            Attach(p2->coef, p2->expon, rear);
            p2 = p2->next;
        }
        if (p2 = NULL)
        {
            Attach(p1->coef, p1->expon, rear);
            p1 = p1->next;
        }
        //将和多项式尾部节点指向空
        rear->next = NULL;
        //销毁头节点,并返回和多项式表头
        temp = front;
        front = front->next;
        free(temp);
        return front;
    }
    
  • 迷宫问题

    • 应用堆栈求解迷宫路径问题基本思路如下:

      • 将初始入口坐标和起始方向信息放入堆栈中。
      • 从堆栈中弹出上次位置信息,设定当前位置和当前尝试方向;若堆栈为空而出口未找到,则该迷宫没有解,程序退出。
      • 在当前位置,从当前方向按顺序尝试剩余方向上的可通行:
        • 若某一方向可通,则将当前位置信息及目前方向信息存入堆栈;
        • 若该可通位置是出口,则成功退出,堆栈中的从栈顶到栈底的各位置顺序构成迷宫路径;
        • 若该可通位置不是出口,将可通位置设为当前位置,并将第一个方向设为当前方向;转到第三步
      • 若8个方向均不可通,则转第二步
    • //相应数据结构为:
      #define MAXMATRIXSIZE 100	//迷宫矩阵最大行列数
      #define MAXSTACKSIZE 100	//堆栈最大规模
      
      //偏移量结构定义
      struct Offsets
      {
          short int Vert;	//纵向偏移
          short int Horiz;	//横向偏移
      };
      
      //迷宫中位置结构
      struct MazePosition
      {
          short int Row;	//行号
          short int Col;	//列号
          short int Dir;	//对应偏移量数组的方向号
      };
      typedef struct MazePosition ElementType;	//堆栈元素类型
      
      //设计一个寻找迷宫路径的函数Path
      void Path(int Maze[][MAXMATRIXSIZE], int EXITROW, int EXITCOL)
      {
          //默认迷宫Maze的入口为(1,1),出口为(EXITROW,EXITCOL)
          //迷宫八个方向的偏移量数组
          struct Offsets Move[8] = {{-1, 0}, {-1, -1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}};
          int Mark[MAXMATRIXSIZE][MAXMATRIXSIZE];	//标记位置是否走过
          Stack S;	//辅助求解的堆栈
          struct MazPosition P;
          short Row, Col, NextRow, NextCol, Dir;
          bool Found = false;
          
          S = CreateStack(MAXMATRIXSIZE);		//初始化堆栈
          
          Mark[EXITROW][EXITCOL] = 1;	//从出口位置开始标记为走过
          
          //将出口位置及下一个方向放入堆栈
          P.Row = EXITROW;
          P.Col = EXITROW;
          P.Dir = 0;
          Push(S, P);
          
          while(!IsEmpty(S) && !Found)
          {
              //当堆栈非空且没找到入口时
              P = Pop(S);	//取出栈顶元素为当前位置
              Row = P.Pow;
              Col = P.Col;
              Dir = P.Dir;
              
              while(Dir < 8 && !found)
              {
                  //当方向可探且没找到入口时
                  //尝试往下一个方向Dir移动
                  NextRow = Row + Move[Dir].Vert;
                  NextCol = Col + Move[Dir].Horiz;
                  if(NextRow == 1 && NextCol == 1)
                  {
                      //如果到达入口,则标记为找到
                      Found = true;
                  }
                  else
                  {
                      //如果下一个位置不是出口
                      if(!Maze[NextRow][NextCol] && !Mark[NextRow][NextCol])
                      {
                          //并且可通还没走过
                          Mark[NextRow][NextCol] = 1;	//标记为走过
                          //将当前位置和下一个方向存入栈
                          P.Row = Row;
                          P.Col = Col;
                          P.Dir = Dir+1;
                          Push(S, P);
                          //更新当前位置,从方向0开始
                          Row = NextRow;
                          Col = NextCol;
                          Dir = 0;
                      }
                      else
                          Dir++;
                  }//结束八方向探索
              }//结束搜索
              if(Found)
              {
                  //找到一个路径,并输出该路径
                  printf("找到路径如下\n");
                  peintf("行 列\n");
                  printf("1 1\n");	//打印入口
                  printf("%d %d\n", Row, Col);	//不要忘记最后一步未入栈
                  while(!IsEmpty(S))
                  {
                      P = Pop(S);
                      printf("%d %d\n", P.Row, P.Col);
                  }
              }
              else	//若没找到路径
                  printf("该迷宫无解。\n");
          }
      }
      

二、学习心得

呵呵哒

标签:return,struct,记录,队列,学习,int,堆栈,数据结构,Stack
From: https://www.cnblogs.com/dragon-dai/p/17643451.html

相关文章

  • *【学习笔记】(10) 块状链表
    块状链表(尚未完善)对于线性表,可以\(O(1)\)的访问,但是插入和删除操作是\(O(n)\)对于链表,可以\(O(1)\)的进行插入和删除,但是是\(O(n)\)的访问。于是本着分块的思想,有了块状链表。大概长这个样子。每个块的大小数量级在\(O(\sqrt{n})\),块数的量级\(O(\sqrt{n})\)主......
  • *【学习笔记】(23) 常用距离算法详解
    本文主要讲述这三种常见距离算法:欧氏距离,曼哈顿距离,切比雪夫距离。1.欧氏距离欧氏距离是最易于理解的一种距离算法。在数学的平面直角坐标系中,设点\(A,B\)的坐标分别为\(A(x_1,y_1),B(x_2,y_2)\),求点\(A,B\)之间的距离,我们一般会使用如下公式:\[\left|AB\right|=......
  • kettle学习
    安装网络上提供的很第三方下载链接失效了,最后找了半天直接去官网下载了。PentahoCommunityEdition.社区版是免费的。点击DownloadNow进行下载。下面的下载目录很多,结合其他教程,下载其中名为pdi-ce-9.4.0.0-343.zip的下载项,当然版本号可能因为更新略有不同。下载过程可能比较......
  • 「学习笔记」莫比乌斯反演
    「学习笔记」莫比乌斯反演点击查看目录目录「学习笔记」莫比乌斯反演前置知识整除分块积性函数线性筛任意积性函数莫比乌斯反演莫比乌斯函数莫比乌斯反演公式例题[HAOI2011]ProblembYY的GCD[SDOI2014]数表DZYLovesMath[SDOI2015]约数个数和[SDOI2017]数字表格于神之......
  • Spring Boot学习笔记day01
    SpringBoot项目结构说明项目____pom.xml:用于管理项目依赖的|_src|_main|_java:蓝色的,写java源代码的|_resource:存放静态资源文件(static目录下)、项目配置文件application.properties、模板文件(template目录下)|_test|_java......
  • Python学习 -- 高阶、闭包、回调、偏函数与装饰器探究
    Python函数作为编程的核心,涵盖了众多令人兴奋的概念,如高阶函数、闭包、回调、偏函数和装饰器。本篇博客将深入研究这些概念,结合实际案例为你解析函数的精妙,以及如何巧妙地运用它们来构建更强大、灵活的程序。高阶函数:进一步探索在上文基础上,再次回顾高阶函数,展示它们如何将函数作为......
  • PaddleOCR学习笔记3-通用识别服务
    今天优化了下之前的初步识别服务的python代码和html代码。采用flask+paddleocr+bootstrap快速搭建OCR识别服务。代码结构如下: 模板页面代码文件如下:upload.html:<!DOCTYPEhtml><html><metacharset="utf-8"><head><title>PandaCodeOCR</title><!-......
  • 强化学习算法如何将GPU利用率提高到100%——在线强化学习如何将GPU利用率提升至100%
    一直有个疑问,那就是“强化学习算法如何将GPU利用率提高到100%”,在一些论坛中也有人会提出这样的问题,但是一直也没有人比较正面的回答过这个问题,为此正好自己又想到了这么一个问题,于是想在这里正面的谈论下这个问题。......
  • python+playwright 学习-74 set_extra_http_headers设置浏览器请求头部
    前言大部分网站保存登录状态是用cookies,也有个别网站是在请求头部添加token实现保存登录。playwright可以使用set_extra_http_headers()方法设置浏览器请求头部参数set_extra_http_headers()方法设置头部参数headers,字典键值对fromplaywright.sync_apiimportsync_pla......
  • SQL注入基础学习
    SQL注入基础一、sql注入的基本知识Ⅰ、sql注入原理通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。通常未经检查或者未经充分检查的用户输入数据或代码编写问题,意外变成了代码被执行。产生漏洞的条件:参数用户可控参......