数据结构(链表、矩阵、串、树、图)


7.7

数据结构

一、基本概念

  • 数据

    是指可以进行操作的具体数据,比如0/1

  • 数据元素

    是数据的基本单位,通常 是被看作一个整体

    由多个数据项或者数据元素组成,其实就是一组数据,比如个人的信息(包含年龄、性别)

  • 数据结构

    各个数据元素之间的关系

    三要素

    1. 逻辑结构

      • 集 合
      • 线性结构
      • 树形结构
      • 图状结构(网状结构)
    2. 物理结构

      其实就是存储结构

      • 顺序存储

        在物理上是连续的

      • 链式存储

        链表

      • 索引存储

        有目录记录 数据所在位置

      • 散列存储

        利用hash值

    3. 数据运算

  • 数据对象

    相同数据结构的集合

  • 数据类型

    值的集合和定义在这集合上的一组操作

  • 抽象数据类型

    抽象的数据组织和相关的运算

二、算法

特性:

  • 输入
  • 输出
  • 有穷性
  • 确定性
  • 可行性

时间复杂度:
在这里插入图片描述

  • ps 求导公式:

    (x^a)'=ax^(a-1)
    (a^x)'=a^xlna
    (logax)'=1/(x*lna)
    (sinx)'=cosx
    (cosx)'=-sinx
    (uv)'=uv'+u'v
    (u+v)'=u'+v'
    (u/v)'=(u'v-uv')/v^2
    

空间复杂度:

  • 原地工作

    是指算法所需要的空间是常数

三、数据结构

1. 线性表
  • 定义 在这里插入图片描述

    线性表是具有相同类型有限个元素的有限序列

  • 分类

    1. 顺序表

      • 相关操作

        插入/删除/查找

        package com.zxc.linearTable.sequence;
        
        /**
         * 功能描述: 顺序表
         * @Author: zxc
         * @Date: 2020/7/18 12:49
         */
        public class options {
            /**
             * 功能描述: 添加
             * @Author: zxc
             * @Date: 2020/7/17 20:53
             */
            private int add(int[] t, int i, int e){
                for (int j = array.CURRENT_SIZE+1; j != i; j--) {
                    t[j]=t[j-1];
                }
                t[i]=e;
                return e;
            }
            /**
             * 功能描述: 删除
             * @Author: zxc
             * @Date: 2020/7/18 12:03
             */
            private void delete(int[] t,int i){
                if (i<0||i>array.CURRENT_SIZE){
                    System.out.println("超出范围");
                }
                for (int j = i; j <array.CURRENT_SIZE ; j++) {
                    t[j]=t[j+1];
                }
            }
            /**
             * 功能描述: 展示
             * @Author: 31262
             * @Date: 2020/7/17 20:52
             */
            private void display(int[] T){
                for (int value : T) {
                    System.out.print(value + " ");
                }
                System.out.println();
            }
        
            public static void main(String[] args) {
                options os=new options();
                int[] t =array.T;
                os.display(t);
                os.add(t,2,777);
        //        os.delete(t,2);
                os.display(t);
            }
        
        
        }
        
        
    2. 单链表
      在这里插入图片描述

      • 头结点是拿来存放想要存放的相关信息,
        也是为了统一空表和非空表的相关操作

      • 头插法建立单链表

      • 尾插法建立单链表

      • 插入

        前插法:由于需要找到目标元素的前一个元素,所以可能需要遍历链表到前一个,但是前插法可以转成后插法,只需先用后插法再交互元素即可

        后插法

      • 删除

        当给定元素的指针的时候,我们只需要交换元素数据,就可以不用找到前一个元素的指针

    package com.zxc.linearTable.linkedList;
    
    import org.hibernate.validator.constraints.EAN;
    
    import java.util.Scanner;
    
    /**
     * 功能描述: 链表
     * @Author: zxc
     * @Date: 2020/7/18 12:48
     */
    public class options {
    
    
        /**
         * 功能描述: 创建(头插法
         * @Author: zxc
         * @Date: 2020/7/22 21:32
         */
        public void createLinkedList(linkedList list){
            Node node=list.getNode();
            Scanner sr=new Scanner(System.in);
            String t="";
            while(true){
                Node newNode=new Node();
                t=sr.next();
                if (t.equals("x"))break;
                newNode.setText(t);
                if (node.getNext()!=null){
                    newNode.setNext(node.getNext());
                }
                node.setNext(newNode);
                node=newNode;
            }
        }
    
    
        /**
         * 功能描述: 尾插法
         * @Author: zxc
         * @Date: 2020/7/23 10:47
         */
        public void createLinkedListByTail(linkedList list){
            Node node=list.getNode();
            Scanner sr=new Scanner(System.in);
            String t="";
            while(true){
                Node newNode=new Node();
                t=sr.next();
                if (t.equals("x"))break;
                newNode.setText(t);
                if (node.getNext()!=null){
                    newNode.setNext(node.getNext());
                }
                node.setNext(newNode);
            }
        }
    
        /**
         * 功能描述: 插入
         * @Author: zxc
         * @Date: 2020/7/22 21:38
         */
        public linkedList insert(linkedList list,String text,int i){
            Node newNode=new Node(text);
            Node node=list.getNode();
    
            for (int j = 0; j < i-1 && node!=null; j++) {
                    node=node.getNext();
            }
            assert node != null;
            newNode.setNext(node.getNext());
            node.setNext(newNode);
            return list;
        }
        /**
         * 功能描述: 删除
         * @Author: zxc
         * @Date: 2020/7/22 22:53
         */
        public linkedList delete(linkedList list,int i){
            Node node=list.getNode();
    
            for (int j = 0; j < i-1 && node!=null; j++) {
                node=node.getNext();
            }
            assert node != null;
            node.setNext(node.getNext().getNext());
            return list;
        }
    
    
    
        /**
         * 功能描述: 展示
         * @Author: zxc
         * @Date: 2020/7/22 22:43
         */
        public void display(linkedList list){
            Node node=list.getNode().getNext();
            while (node!=null){
                System.out.print(node.getText()+"=>");
                node=node.getNext();
            }
        }
    
        public static void main(String[] args) {
            options os=new options();
            linkedList list=new linkedList();
    
            os.createLinkedListByTail(list);
    //        os.insert(list,"a",1);
    //        os.insert(list,"b",2);
    //        os.insert(list,"c",3);
    //        os.insert(list,"d",4);
    //        os.insert(list,"e",5);
    
    //        os.delete(list,2);
            os.display(list);
        }
    
    }
    
    1. 双向链表

      • 如单项链表一样操作
    2. 循环链表(单/双)

      • 只是给最后一个数据元素的后继指针指向头指针
      package com.zxc.linearTable.doublyLinkedList;
      
      import com.zxc.linearTable.doublyLinkedList.Node;
      import com.zxc.linearTable.doublyLinkedList.linkerList;
      
      import java.util.Scanner;
      
      /**
       * 功能描述: 双向链表
       * @Author: zxc
       * @Date: 2020/7/18 12:48
       */
      public class options {
      
      
          /**
           * 功能描述: 创建(头插法
           * @Author: zxc
           * @Date: 2020/7/22 21:32
           */
          public void createLinkedList(linkerList list){
              Node node=list.getNode();
              Scanner sr=new Scanner(System.in);
              String t="";
              while(true){
                  Node newNode=new Node();
                  t=sr.next();
                  if (t.equals("x")) {
                      break;
                  }
                  newNode.setText(t);
                  newNode.setNext(node.getNext());
                  newNode.setPre(node);
                  node.setNext(newNode);
                  if (null!=newNode.getNext()){
                      newNode.getNext().setPre(newNode);
                  }
                  node=newNode;
              }
          }
      
      
          /**
           * 功能描述: 尾插法
           * @Author: zxc
           * @Date: 2020/7/23 10:47
           */
          public void createLinkedListByTail(linkerList list){
              Node node=list.getNode();
              Scanner sr=new Scanner(System.in);
              String t="";
              while(true){
                  Node newNode=new Node();
                  t=sr.next();
                  if (t.equals("x"))break;
                  newNode.setText(t);
                  newNode.setNext(node.getNext());
                  newNode.setPre(node);
                  node.setNext(newNode);
                  if (null!=newNode.getNext())
                  newNode.getNext().setPre(newNode);
              }
          }
      
          /**
           * 功能描述: 插入
           * @Author: zxc
           * @Date: 2020/7/22 21:38
           */
          public linkerList insert(linkerList list,String text,int i){
              Node newNode=new Node();
              Node node=list.getNode();
      
              for (int j = 0; j < i-1 && node!=null; j++) {
                      node=node.getNext();
              }
              assert node != null;
              newNode.setText(text);
              newNode.setNext(node.getNext());
              newNode.setPre(node.getPre());
              node.getNext().setPre(newNode);
              node.setNext(newNode);
              return list;
          }
          /**
           * 功能描述: 删除
           * @Author: zxc
           * @Date: 2020/7/22 22:53
           */
          public linkerList delete(linkerList list,int i){
              Node node=list.getNode();
      
              for (int j = 0; j < i-1 && node!=null; j++) {
                  node=node.getNext();
              }
              assert node != null;
              if (node.getNext().getNext()!=null){
                  node.getNext().getNext().setPre(node);
              }
              node.setNext(node.getNext().getNext());
              return list;
          }
      
      
      
          /**
           * 功能描述: 展示
           * @Author: zxc
           * @Date: 2020/7/22 22:43
           */
          public void display(linkerList list){
              Node node=list.getNode().getNext();
              while (node!=null){
                  System.out.print(node.getText()+"=>");
                  node=node.getNext();
              }
              System.out.println();
          }
      
          public static void main(String[] args) {
              options os=new options();
              linkerList list=new linkerList();
      
              os.createLinkedList(list);
              os.display(list);
      
              os.insert(list,"a",3);
      //        os.insert(list,"b",2);
      //        os.insert(list,"c",3);
      //        os.insert(list,"d",4);
      //        os.insert(list,"e",5);
      
              os.delete(list,2);
              os.display(list);
          }
      
      }
      
    3. 静态链表

      就是用数组表示链表,

    • 常见操作

      1. 最值

        /**
         * 功能描述: 寻找最小值
         * @Author: zxc
         * @Date: 2020/7/23 13:47
         */
        public int findMin(linkedList list){
            Node node=list.getNode().getNext();
            int min=Integer.parseInt(node.getText());
            while (node!=null){
                if (Integer.parseInt(node.getText())<min){
                    min=Integer.parseInt(node.getText());
                }
                node=node.getNext();
            }
            return min;
        }
        /**
         * 功能描述: 寻找最大值
         * @Author: zxc
         * @Date: 2020/7/23 13:47
         */
        public int findMax(linkedList list){
            Node node=list.getNode().getNext();
            int max=Integer.parseInt(node.getText());
            while (node!=null){
                if (Integer.parseInt(node.getText())>max){
                    max=Integer.parseInt(node.getText());
                }
                node=node.getNext();
            }
            return max;
        }
        
      2. 逆置

        /**
         * 功能描述: 逆置
         * @Author: zxc
         * @Date: 2020/7/23 14:16
         */
        public void reserve(linkedList list){
            Node header=new Node();
            Node temp;
            Node node=list.getNode();
            while (node.getNext()!=null){
                temp=node.getNext();
                node.setNext(node.getNext().getNext());
                temp.setNext(header.getNext());
                header.setNext(temp);
            }
            list.setNode(header);
        }
        
      3. 有序归并

        /**
         * 功能描述: 有序归并
         * @Author: zxc
         * @Date: 2020/7/23 14:32
         */
        public linkedList orderlyMerging(linkedList l1,linkedList l2){
            linkedList re=new linkedList();
            Node n1=l1.getNode().getNext();
            Node n2=l2.getNode().getNext();
            Node n3=re.getNode();
            int s1=Integer.parseInt(l1.getNode().getText());
            int s2=Integer.parseInt(l2.getNode().getText());
            for (;n1!=null&&n2!=null;){
                if (Integer.parseInt(n1.getText())<Integer.parseInt(n2.getText())){
                    n3.setNext(n1);
                    n1=n1.getNext();
                }else{
                    n3.setNext(n2);
                    n2=n2.getNext();
                }
                n3=n3.getNext();
            }
            while(n1!=null){
                n3.setNext(n1);
                n1=n1.getNext();
            }
            while(n2!=null){
                n3.setNext(n2);
                n2=n2.getNext();
            }
            return re;
        }
        
2.
  • 定义

    只允许在一端进行拿/取的数据结构

在这里插入图片描述

  • 分类

    1. 顺序存储

      利用数组来实现顺序存储元素,再加上一个top指针指向栈顶元素,方便进行进栈、出栈的操作

      package com.zxc.stack.linear;
      
      /**
       * 功能描述: 栈
       * @Author: zxc
       * @Date: 2020/7/24 10:56
       */
      public class options {
          /**
           * 功能描述: 初始化顺序空栈
           * @Author: zxc
           * @Date: 2020/7/24 10:57
           */
          public void initStack(linearStack stack){
              stack.top=-1;
          }
      
          /**
           * 功能描述: 判断栈空
           * @Author: zxc
           * @Date: 2020/7/24 10:59
           */
          boolean stackEmpty(linearStack s){
              return s.top == -1;
          }
      
          /**
           * 功能描述: 进栈
           * @Author: zxc
           * @Date: 2020/7/24 11:01
           */
          boolean push(linearStack stack,int x){
              if (stack.top==stack.MAX_SIZE-1){
                  return false;
              }
              stack.data[++stack.top]=x;
              return true;
          }
      
          /**
           * 功能描述: 出栈
           * @Author: zxc
           * @Date: 2020/7/24 11:09
           */
          public int pop(linearStack stack){
              if (stack.top==-1){
                  return -1;
              }
              return stack.data[stack.top--];
          }
          /**
           * 功能描述: 展示
           * @Author: zxc
           * @Date: 2020/7/24 11:09
           */
          public void display(linearStack stack){
              for (int i = 0; i <= stack.top; i++) {
                  System.out.print(stack.data[i]+"=>");
              }
              System.out.println();
          }
          /**
           * 功能描述: 获取栈顶元素
           * @Author: zxc
           * @Date: 2020/7/24 11:18
           */
          public int getTop(linearStack stack){
              return stack.data[stack.top];
          }
      
      
          public static void main(String[] args) {
              linearStack stack=new linearStack();
              options os=new options();
              os.initStack(stack);
      
              os.push(stack,1);
              System.out.println(os.getTop(stack));
              os.push(stack,2);
              os.push(stack,3);
              System.out.println(os.getTop(stack));
              os.push(stack,4);
      
      
              System.out.println(os.pop(stack));
              os.display(stack);
          }
      }
      

      tips:共享栈 使用两个指针,相当于是将两个栈的栈底链接起来,能更有效的利用空间,就比如我们拿羽毛球 球桶,可以从底部拿出来

    在这里插入图片描述

    1. 链式存储

      和链表类似,但是没有头结点,指针直接指向了栈顶元素,方便进行栈顶的元素操作

在这里插入图片描述

3.队列
  • 定义

    可以简单理解为,只能在队列一端进行删除,另一端进行插入的表

  • 分类

    1. 顺序存储

      还是利用数组来进行实现,可以发现这个和之前讲的栈有点相像,只不过是多了一个队头的指针,
      (特别需要注意的是,front指针是队头指针 直接指向队头,rear是队尾指针 直接指向的是队尾元素的后一位,这是为了后续操作的方便性)

      在这里插入图片描述


    这里特别提出来一个问题,当我们不断地进行入栈出栈的操作后,front和rear会不断地被往后推移,最终会导致rear被推到数组的尾部,如下:

在这里插入图片描述

这就会有小伙伴说,直接判断它溢出不就解决了?当front处于很数组前几位时,的确可以,但是当front也被推送到数组尾部附近时,会造成前面大量空间的浪费(可以称为假溢出)。

为了解决这个问题,引出了循环队列

也就是把存储队列的顺序队列逻辑上视为环,如下:

在这里插入图片描述

那么如何做呢?其实可以通过取余的操作

  • front指针移动

    (q.front+1)%MaxSize

  • rear指针移动

    (q.rear+1)%MaxSize

  • 队列长度

    (q.rear-q.front+MaxSize)%MaxSize

判断循环队列是否满/空

因为循环队列,所以队空和队满的情况变得一样,有以下几种解决办法:

  1. 牺牲一个存储单元

在这里插入图片描述

  1. 增加一个变量代表元素的个数

    也就是增加一个位置的数,表示队列所在的元素个数

  2. 增加tag标识

    因为 队列空 是由出队操作引起;

    ​ 队列满 是由入队操作引起;

    所以,我们针对操作后设置一个变量 tag标记该操作是入队还是出队

在这里插入图片描述


  1. 链式存储

    一般还是采用带有头结点的队列

tips:有可能的出栈和入栈序列,只需要尝试就好了

  1. 双端队列

    允许两端都允许出队和入队的操作

在这里插入图片描述

  • 相关应用

    1. 括号匹配:

在这里插入图片描述

  1. 表达式求值

在这里插入图片描述

 中缀转后缀,利用栈进行实现

在这里插入图片描述

4. 矩阵和数组

数组只需知道它的物理存储地址是连续存储的

下面重点介绍矩阵:

  • 定义

    矩阵可以简单的理解为二维数组

  • 压缩存储

    指多个值相同的元素只分配一个空间,对零元素不进行分配

    特殊矩阵 是指具有许多的相同矩阵元素或者零元素,且分布具有一定性的规律的矩阵

    特殊矩阵的分类

    1. 对称矩阵

      对于矩阵中的任意元素,都有Aij=Aji
      在这里插入图片描述

      所以对称矩阵只需存储接近一半多一点的元素

    2. 三角矩阵

      对于一个矩阵,上三角或者下三角都是相同的元素,在这里插入图片描述

    3. 三对角矩阵

    4. 稀疏矩阵

      零元素是非常多的

在这里插入图片描述

5. 串
  • 定义

    是由0个或多个字符组成的有序序列,且以\0表示字符串截至

]

概念解释
子串在串中的任意个连续的字符
  • 分类

    1. 顺序存储

    2. 堆分配存储

    3. 块链存储

在这里插入图片描述

  • 串的匹配模式

  • KMP算法

矩阵:

  • 定义

    矩阵可以简单的理解为二维数组

  • 压缩存储

    指多个值相同的元素只分配一个空间,对零元素不进行分配

    特殊矩阵 是指具有许多的相同矩阵元素或者零元素,且分布具有一定性的规律的矩阵

    特殊矩阵的分类

    1. 对称矩阵

      对于矩阵中的任意元素,都有Aij=Aji[外链图片转存中…(img-IEq5kujS-1595655913307)]

      所以对称矩阵只需存储接近一半多一点的元素

    2. 三角矩阵

      对于一个矩阵,上三角或者下三角都是相同的元素,[外链图片转存中…(img-Bnf6fbY6-1595655913308)]

    3. 三对角矩阵

    4. 稀疏矩阵

      零元素是非常多的

      [外链图片转存中…(img-5BqUA0Cl-1595655913309)]

5. 串
  • 定义

    是由0个或多个字符组成的有序序列,且以\0表示字符串截至

    [外链图片转存中…(img-QFMAEXy8-1595655913310)]

    概念解释
    子串在串中的任意个连续的字符
  • 分类

    1. 顺序存储

    2. 堆分配存储

    3. 块链存储

      [外链图片转存中…(img-rtnrjzF0-1595655913311)]

  • 串的匹配模式

  • KMP算法

6.树

----------------------------------------------------- 在更

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值