数据结构与算法


数据结构与算法

数据结构与算法的概述

数据结构与算法的介绍

  • 算法

    • 算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。

    • 算法是独立存在的一种解决问题的方法和思想。

      • 对于算法而言,实现的语言并不重要,重要的是思想。
    • 算法可以有不同的语言描述实现版本(如C描述、C++描述、Python描述等)

    • 案列一

      • 有一个背包,背包容量是M=150。有7个物品,物品可以分割成任意大小。要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。
    • 案列二

      • 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第4个月后,每个月又生一对兔子,假如兔子不死,问每个月的兔子总数为多少?
  • 数据结构

    • 数据结构就是把数据组织起来,为了更方便地使用数据我们为了解决问题,需要将数据保存下来,然后根据数据的存储方式来设计算法实现进行处理,那么数据的存储方式不同就会导致需要不同的算法进行处理。我们希望算法解决问题的效率越快越好,于是我们就需要考虑数据究竟如何保存的问题,这就是数据结构。
    • 数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。

数据结构与算法关系

  • 程序 = 数据结构 + 算法
  • 数据结构是算法的基础。
  • 图书馆储藏书籍你肯定见过吧?为了方便查找,图书管理员一般会将书籍分门别类进行“存储”。按照一定规律编号,就是书籍这种“数据”的存储结构。
  • 那我们如何来查找一本书呢?有很多种办法,你当然可以一本一本地找,也可以先根据书籍类别的编号,是人文,还是科学、计算机,来定位书架,然后再依次查找。笼统地说,这些查找方法都是算法。
  • 数据结构和算法是相辅相成的。数据结构是为算法服务的,算法要作用在特定的数据结构之上。 因此,我们无法孤立数据结构来讲算法,也无法孤立算法来讲数据结构。

线性结构和非线性结构

  • 线性结构

    • 线性结构作为最常用的数据结构,其特点是数据元素之间存在一对一的线性关系。
    • 线性结构有两种不同的存储结构,即顺序存储结构(数组)和链式存储结构(链表)。顺序存储的线性表称为顺序表,顺序表中的存储元素是连续的。
    • 链式存储的线性表称为链表,链表中的存储元素不一定是连续的,元素结点存放数据元素以及相邻元素的地址信息。
    • 线性结构常见的有:数组、队列、链表和栈。

    线性表的顺序存储图

  • 非线性结构

    • 二维数组、多维数组、广义表、树结构、图结构

      树状结构图


栈的介绍

  • 栈是限制插入和删除只能在一个位置上进行的线性表。

  • 其中,允许插入和删除的一端位于表的末端,叫做栈顶(top),不允许插入和删除的另一端叫做栈底(bottom)。对栈的基本操作有 PUSH(压栈)POP (出栈),前者相当于表的插入操作(向栈顶插入一个元素),后者则是删除操作(删除一个栈顶元素)。栈是一种后进先出(LIFO)**的数据结构,最先被删除的是最近压栈的元素。

  • 栈的结构图

    栈结构图

  • 压栈图

    压栈图

  • 弹栈图

    弹栈图

  • 栈实现

    • 由于栈是一个表,因此任何实现表的方法都可以用来实现栈。主要有两种方式,链表实现和数组实现。
  • 链表实现块

    • 可以使用单链表来实现栈。通过在表顶端插入一个元素来实现 PUSH,通过删除表顶端元素来实现 POP。使用链表方式实现的栈又叫动态栈。动态栈有链表的部分特性,即元素与元素之间在物理存储上可以不连续,但是功能有些受限制,动态栈只能在栈顶处进行插入和删除操作,不能在栈尾或栈中间进行插入和删除操作
  • 数组实现块

    • 栈也可以用数组来实现。使用数组方式实现的栈叫静态栈

栈的应用场景

  • 子程序的调用,在跳往子程序前,会将下一个指令的地址存到堆栈中,知道子程序执行完后再将地址取出,以回到原来的程序中。
  • 处理递归调用:和子程序的调用类似,只是除了存储下一个指令的地址外,也将参数,区域变量等数据存入堆栈中。
  • 表达式的转换:【中缀表达式转后缀表达式】与求值()实际解决

栈的快速入门

  • 练习:使用数组来模拟栈

    public class ArrayStack {
    
        //定义栈的大小
        private int maxStack;
    
        //定义一个数组来模拟栈
        private int[] stack;
    
        //栈帧所在的位置,默认情况下没有数据返回-1
        private int top = -1;
    
        //使用构造函数初始化栈的大小
        public ArrayStack(int maxStack) {
            this.maxStack = maxStack;
            stack = new int[maxStack];
        }
    
        /**
         * 压栈
         * 弹栈
         * 判断栈中是否为空
         * 判断栈中是否已满
         */
    
        /**
         * 先判断是否为空栈
         */
        public boolean isNull(){
            return this.top == -1;
        }
    
        /**
         * 判断是否为满栈
         */
        public boolean isFull(){
            return this.top == stack.length-1;
        }
    
        /**
         * 压栈
         */
        public void posh(int i){
            //先判断栈是否满栈,若满栈则抛出异常
            if (isFull()){
                throw new RuntimeException("栈已满!!");
            }
            stack[++top] = i;
        }
    
        /**
         * 弹栈
         */
        public int pop(){
            //先判断栈是否为空
            if (isNull()){
                throw new RuntimeException("栈已空!!");
            }
            int value = stack[top--];
            return value;
        }
    
        /**
         * 查看栈中所有的元素
         */
        public void list(){
            if (isNull()){
                throw new RuntimeException("空栈,没有找到数据");
            }
            for (int i : stack) {
                System.out.println(i);
            }
        }
    
        /**
         * 栈中元素的个数
         */
        public int length(){
            return this.top+1;
        }
    }
    
  • 测试:使用模拟的栈来测试一个字符串是否是回文数据。

    • 回文数据:就是压栈前,与弹栈后的字符串相同
    • 例如:aba , abcba就是回文数据
    public class TestApp {
        public static void main(String[] args) {
            /**
             * 回文数据
             * 回文:aba   abcdcba
             * 回文就是正反过来数据不会变
             * 下面,由模拟的栈来判断一个字符串是否是回文数据
             */
            boolean abc = method("aba");
            System.out.println(abc);
        }
    
        //定义方法,调用栈来测试字符串是否为回文数据
        public static boolean method(String s){
            /**
             * 初始化栈对象
             */
            ArrayStack arrayStack = new ArrayStack(10);
            /**
             * 获取字符串
             * 将字符串压入栈中
             */
            for (int i = 0; i < s.length(); i++) {
               arrayStack.posh(s.charAt(i));
            }
    
            /**
             * 获取栈中的数据
             */
            //定义一个字符串
            String s1 = "";
            int length = arrayStack.length();
            for (int i = 0; i < length; i++) {
                if (arrayStack.isNull()){
                    throw new RuntimeException("空栈");
                }
                char pop = (char)arrayStack.pop();
                s1 += pop;
            }
    
            return s.equals(s1);
        }
    }
    

链表

链表(Linked List)介绍

-


文章作者: 勾魂大猩猩
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 勾魂大猩猩 !
  目录