数据结构与算法(二):线性表

2023-11-12


上一篇《数据结构与算法(一):概述》中介绍了数据结构的一些基本概念,并分别举例说明了算法的时间复杂度和空间复杂度的求解方法。这一篇主要介绍线性表。

一、基本概念

线性表是具有零个或多个数据元素的有限序列。线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的。

线性表的基本特征:

  • 第一个数据元素没有前驱元素;
  • 最后一个数据元素没有后继元素;
  • 其余每个数据元素只有一个前驱元素和一个后继元素。

抽象数据类型:

线性表一般包括插入、删除、查找等基本操作。其基于泛型的API接口代码如下:

public interface List<E> {
    //线性表的大小
    int size();

    //判断线性表是否为空
    boolean isEmpty();

    void clear();

    //添加新元素
    void add(E element);

    //在指定位置添加新元素
    void add(int index, E element);

    //删除元素
    E delete(int index);

    //获取元素
    E get(int index);
}

线性表按物理存储结构的不同可分为顺序表(顺序存储)和链表(链式存储):

  • 顺序表(存储结构连续,数组实现)
  • 链表(存储结构上不连续,逻辑上连续)

二、顺序表

顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构。线性表采用顺序存储的方式存储就称之为顺序表。

其插入删除操作如图所示:

在这里插入图片描述

注意:

  • 插入操作:移动元素时,要从后往前操作,不能从前往后操作,不然元素会被覆盖。
  • 删除操作:移动元素时,要从前往后操作。
    代码如下:
import java.util.*;
public class SequenceList<E> implements List<E>, Iterable<E> {

    private static final int DEFAULT_CAPACITY = 10;
    private int size;
    private E[] elements;

    @SuppressWarnings("unchecked")
    public SequenceList() {
        size = 0;
        elements = (E[])new Object[DEFAULT_CAPACITY];
    }

    public int size() { return size;}

    public boolean isEmpty(){ return size == 0;}

    @SuppressWarnings("unchecked")
    public void clear(){
        size = 0;
        elements = (E[])new Object[DEFAULT_CAPACITY];
    }

    public void add(E element){ 
        add(size, element);
    }

    //在index插入element
    public void add(int index, E element){
        if(size >= elements.length) {
            throw new RuntimeException("顺序表已满,无法添加"); 
        }
        if(index < 0 || index > size) {
            throw new IndexOutOfBoundsException("参数输入错误"); 
        }
        for(int i=size; i>index; i--) {
            elements[i] = elements[i - 1];
        }
        elements[index] = element;
        size++;
    }

    //删除元素
    public E delete(int index){
        if(isEmpty()) {
            throw new RuntimeException("顺序表为空,无法删除"); 
        }
        if(index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("参数输入错误"); 
        }
        E result = elements[index];
        for(int i=index; i<size - 1; i++) {
            elements[i] = elements[i + 1];
        }
        size--;
        elements[size] = null; //避免对象游离
        return result;
    }

    public E get(int index){
        if(index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("参数输入错误"); 
        }
        return elements[index];
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            int num = 0;
            @Override
            public E next() {                
                return elements[num++];
            }

            @Override
            public boolean hasNext() {
                return num < size;
            }
        };
    }

    public static void main(String[] args) {
        SequenceList<Integer> sl = new SequenceList<Integer>();
        for(int i=0;i<10;i++) {
            sl.add(i);
        }
        System.out.println("删除1位置元素:"+sl.delete(1));
         sl.add(0,15);
        for(int i=0;i<sl.size();i++) {
            System.out.print(sl.get(i)+" ");
        }
    }
}

这里需要注意,由于java中不能直接创建泛型数组,所以在顺序表的构造函数中先创建了一个Object的数组,然后将它强转为泛型数组并使用@SuppressWarnings(“unchecked”)消除未受检的警告。若对这点还有什么疑问可以参考我的学习笔记 Effective java笔记(四),泛型 中第25、26条。另外在进行删除操作时应避免对象游离。

在java中,数组一旦创建其大小不能改变,所以在上面的实现中,为了尽可能的不浪费内存必须事先准确的预估顺序表的容量。但现实应用中由于存在很多不确定因素,这往往是不切实际的。这时可使用动态调整数组大小的方法来解决这个问题。代码如下:

private void resize(int num){
    @SuppressWarnings("unchecked")
    E[] temp = (E[]) new Object[num];
    for(int i=0; i<size; i++) {
        temp[i] = elements[i];
    }
    elements = temp;
}

然后在插入和删除操作中分别加入判断语句,来调用这个方法

//在index插入element
public void add(int index, E element){
    //当顺序表满时,容量加倍
    if(size >= elements.length) {
        // throw new RuntimeException("顺序表已满,无法添加"); 
        resize(elements.length*2);
    }
    if(index < 0 || index > size) {
        throw new IndexOutOfBoundsException("参数输入错误"); 
    }
    ....
}

//删除元素
public E delete(int index){
    ....
    elements[size] = null;

    //当元素数量小于容量的1/4时,容量减半
    if(size>0 && size <= elements.length/4) {
        resize(elements.length/2);
    }
    return result;
}

**注意:**在删除操作中检查条件为「顺序表的大小是否小于容量的 1/4」,而不是1/2。这样可以避免在1/2这个零界点处反复进行插入删除操作时,数组进行频繁复制。

顺序表效率分析:

  • 顺序表插入和删除一个元素,最好情况下其时间复杂度(这个元素在最后一个位置)为O(1),最坏情况下其时间复杂度为O(n)。
  • 顺序表支持随机访问,读取一个元素的时间复杂度为O(1)。

顺序表的优缺点:

  • 优点:支持随机访问
  • 缺点:插入和删除操作需要移动大量的元素,造成存储空间的碎片。
    顺序表适合元素个数变化不大,且更多是读取数据的场合。

三、链表

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点组成,每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

链表根据构造方式的不同可以分为:

  • 单向链表
  • 单向循环链表
  • 双向链表

1、单向链表

单链表有带头结点和不带头结点两种结构,其结构如下

在这里插入图片描述

在带头结点的单链表中,其第一个结点被称作头结点。第一个存放数据元素的结点称作首元结点,头结点指向首元结点。头结点是为了操作的统一与方便而设立的,其一般不放数据(也可存放链表的长度、用做监视哨等)。此结点不能计入链表长度值。

带头结点的单链表的优点:

  • 在链表第一个位置上进行的操作(插入、删除)和其它位置上的操作一致,无须进行特殊处理;
  • 无论链表是否为空,head一定不为空,这使得空表和非空表的处理一致。

由于带头结点的链表更容易操作,这里仅实现带头结点的单链表

带头结点的链表插入与删除示意图:

在这里插入图片描述

代码如下:

import java.util.*;
public class LinkedList<E> implements List<E>, Iterable<E>{
    private Node head;
    private int size;

    private class Node {
        E element;
        Node next;
    }

    LinkedList() {
        head = new Node();
    }

    @Override public int size() { return size;}
    
    @Override public boolean isEmpty() { return size==0;}

    @Override public void clear() {
        head = new Node();
        size = 0;
    }

    @Override public void add(E element) {
        add(0, element);
    }

    @Override public void add(int index, E element) {
        if(index < 0 || index > size)
            throw new IndexOutOfBoundsException("参数输入错误");
        Node current = location(index);
        Node newNode = new Node();
        newNode.element = element;        
        Node node = current.next;
        current.next = newNode;
        newNode.next = node;
        size++;
    }

    //找到第index个结点前的结点
    private Node location(int index){
        Node current = head;
        for(int i=0; i<index; i++) {
            current = current.next;
        }
        return current;
    }
    
    @Override public E get(int index) {
        if(index < 0 || index >= size)
            throw new IndexOutOfBoundsException("参数输入错误");
        return location(index + 1).element;
    }

    //删除第index个元素
    @Override public E delete(int index) {
        if(index < 0 || index >= size)
            throw new IndexOutOfBoundsException("参数输入错误");
        Node current = location(index);
        E element = current.next.element;
        current.next = current.next.next;
        size--;
        return element;
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            Node current = head;
            @Override
            public E next() {  
                current = current.next;              
                return current.element;
            }

            @Override
            public boolean hasNext() {
                return current.next != null;
            }
        };
    }

    public static void main(String[] args) throws Exception{
        LinkedList<Integer> list = new LinkedList<Integer>();
        for(int i=0;i<10;i++) {
            list.add(i);
        }
        System.out.println("删除0位置元素:"+list.delete(0));
        list.add(0,15);

        for (Integer ele : list ) {
            System.out.print(ele + " ");
        }
    }
}

单链表效率分析:

在单链表上插入和删除数据时,首先需要找出插入或删除元素的位置。对于单链表其查找操作的时间复杂度为 O(n),所以

链表插入和删除操作的时间复杂度均为 O(n)

链表读取操作的时间复杂度为 O(n)

单链表优缺点:

优点:不需要预先给出数据元素的最大个数,单链表插入和删除操作不需要移动数据元素
缺点:不支持随机读取,读取操作的时间复杂度为 O(n)。

2、单向循环链表

将单链表中终端结点的指针指向头结点,使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表。

对于循环链表,为了使空链表与非空链表处理一致,通常设一个头结点。如下图:

在这里插入图片描述

循环链表和单链表的主要差异在于链表结束的判断条件不同,单链表为current.next是否为空,而循环链表为current.next不等于头结点。对于循环链表的增删改查操作与单链表基本相同,仅仅需要将链表结束的条件变成current.next != head即可,这里就不在给出了。

在单链表中,我们有了头结点时,对于最后一个结点的访问需要 O(n)的时间,因为我们需要将单链表全部遍历一次。哪有没有可能用 O(1)的时间访问到终端结点呢?当然可以,我们只需改造一下单链表,使用指向终端结点的尾指针来表示循环链表,这时访问开始结点(不是头结点)和终端结点的操作都为 O(1)。它们的访问操作分别为end.next.next和end,其中end为指向终端结点的引用。这个设计对两个循环链表的合并特别有用,可以避免遍历链表的时间消耗。如:

在这里插入图片描述

合并两个循环链表的代码:

public Node merge(Node endA, Node endB) {
    Node headA = endA.next; //保存A表的头结点
    endA.next = endB.next.next;
    endB.next = headA;
    return endB;
}

3、双向链表

双向链表是在单链表的每个结点中,再设置一个指向其前驱结点的指针域。使得两个指针域一个指向其前驱结点,一个指向其后继结点。

双向链表的结点表示:

private class Node {
    E element;
    Node prior; //指向前驱
    Node next;
}

对于双向链表,其空和非空结构如下图:

在这里插入图片描述

双向链表是单链表扩展出来的结构,它可以反向遍历、查找元素,它的很多操作和单链表相同,比如求长度size()、查找元素get()。这些操作只涉及一个方向的指针即可。插入和删除操作时,需要更改两个指针变量。

插入操作:注意操作顺序
在这里插入图片描述

在current后插入element的代码为:

element.prior = current;
element.next = current.next;
current.next.prior = element;
current.next = element;

删除操作相对比较简单,删除current结点的代码为:

current.prior.next = current.next;
current.next.prior = current.prior;
current = null;

双向链表相对于单链表来说占用了更多的空间,但由于其良好的对称性,使得能够方便的访问某个结点的前后结点,提高了算法的时间性能。是用空间换时间的一个典型应用。

4、静态链表

用数组描述的链表叫静态链表,它是那些没有指针和引用的语言,如Basic、Fortran等,实现链表的方式。由于现在的高级程序语言,一般都拥有指针或引用,可以使用更灵活的指针或引用来实现动态链表,所以对于静态链表仅掌握其算法思想即可。

静态链表的思想:

  • 让数组的每个元素有两个数据域data和cur组成,其中data用来存放数据元素,cur用来存放元素的后继在数组中的下标。我们把cur称为游标。

  • 通常把数组中未被使用的位置称为备用链表,而数组的第一个位置(下标为0的位置)的cur存放备用链表的第一个结点的下标;数组的最后一个位置的cur则存放第一个有元素的位置的下标,相当于链表的头结点作用。

静态链表状态图:

在这里插入图片描述

代码如下:

import java.util.*;
public class StaticList<E> implements List<E>, Iterable<E> {

    private static final int DEFAULT_CAPACITY = 100;
    private int size;
    private Node[] nodes;

    private class Node {
        E element;
        int cur;
    }

    public StaticList() {
        initList();
        
    }

    @SuppressWarnings("unchecked")
    private void initList() {
        size = 0;
      //注意这句,不能直接new Node[DEFAULT_CAPACITY],java不允许创建泛型数组
        nodes = new StaticList.Node[DEFAULT_CAPACITY]; 
        for(int i=0; i<nodes.length; i++) {
            nodes[i] = new Node();
            nodes[i].cur = i + 1;
        }
        nodes[nodes.length - 1].cur = 0;
    }

    public int size() { return size;}

    public boolean isEmpty(){ return size == 0;}

    public void clear(){
        initList();
    }

    public void add(E element){ 
        add(0, element);
    }

    //在index插入element
    public void add(int index, E element){
        if(index < 0 || index > size) {
            throw new IndexOutOfBoundsException("参数输入错误"); 
        }
        Node prior = location(index);
        int newCur = malloc();
        if(newCur == 0) {
            throw new RuntimeException("顺序表已满,无法添加");
        }
        nodes[newCur].element = element;
        nodes[newCur].cur = prior.cur;
        prior.cur = newCur;
        size++;
    }

    //找到第index个结点前的结点
    private Node location(int index){
        Node prior = nodes[nodes.length - 1];
        for(int i=0; i<index; i++) {
            prior = nodes[prior.cur];
        }
        return prior;
    }

    //分配空间,若备用链表非空,返回分配的结点的下标,否则返回0
    private int malloc() {
        int i = nodes[0].cur;
        if(i != 0) {
            nodes[0].cur = nodes[i].cur; //备用链表的下一个位置
        }
        return i;
    }

    //将下标为k的空闲结点回收到备用链表
    private void free(int index) {
        nodes[index].cur = nodes[0].cur;
        nodes[0].cur = index;
    }

    //删除元素
    public E delete(int index){
        if(isEmpty()) {
            throw new RuntimeException("顺序表为空,无法删除"); 
        }
        if(index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("参数输入错误"); 
        }
        Node prior = location(index);
        int temp = prior.cur; //要删除元素的下标
        prior.cur = nodes[temp].cur;
        E result = nodes[temp].element;
        nodes[temp].element = null;
        size--;
        free(temp);
        return result;
    }

    public E get(int index){
        if(index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("参数输入错误"); 
        }
        return location(index + 1).element;
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            int temp = nodes[nodes.length - 1].cur;
            @Override
            public E next(){  
                E result = nodes[temp].element;  
                temp = nodes[temp].cur;          
                return result;
            }

            @Override
            public boolean hasNext() {
                return temp != 0;
            }
        };
    }
    
    //测试
    public static void main(String[] args){
        StaticList<Integer> sl = new StaticList<Integer>();
        for(int i=0;i<10;i++) {
            sl.add(i);
        }
        System.out.println("删除1位置元素:"+sl.delete(1));
         sl.add(1,15);
        for(int i=0;i<sl.size();i++) {
            System.out.print(sl.get(i)+" ");
        }
    }
}

为了实现数组空间的循环利用,静态链表将所有未被使用过的及已经被删除的元素空间用游标链成一个备用的链表。每当插入时就从备用链表上取第一个结点作为待插入的新结点,删除时将结点回收到备用链表中。上面代码中的malloc()和free()方法分别对应了这两种操作。静态链表的插入和删除等操作和单链表类似,仅需注意结点的cur为一个int变量,具体操作可以参考上面的代码。

另外需要注意:静态链表初始化时需要创建一个内部类泛型数组StaticList.Node[ ],我们都知道,java中不能创建泛型数组,一种解决方案是先创建一个Object类型的数组,然后再强转为需要的类型。如:

nodes = (Node[])new Object[DEFAULT_CAPACITY]; 

但是在上面的代码中,使用这种方法运行时会报ClassCastException,解决方法是

nodes = new StaticList.Node[DEFAULT_CAPACITY];

这样就可以解决这个问题,剩下一个未受检的警告使用@SuppressWarnings(“unchecked”)注解消除即可。

静态链表有优缺点:

  • 优点:插入删除操作时,只需要修改游标,无需移动元素

  • 缺点:需要事先预估链表的容量;不能随机读取元素;需要人为的管理数组的分配(类似于管理内存分配),失去了java语言的优点。

总的来说,静态链表是为没有指针的语言设计的一种实现链表的方法,尽管可能用不上,但掌握其设计思想还是很有必要的。

总结一下,这节主要介绍了线性表两种不同结构(顺序存储结构和链式存储结构)的实现方法,它们是其他数据结构的基础,也是现在企业面试中最常考的数据结构类型之一。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构与算法(二):线性表 的相关文章

  • 如何使用 Java 和 Selenium WebDriver 在 C 目录中创建文件夹并需要将屏幕截图保存在该目录中?

    目前正在与硒网络驱动程序和代码Java 我有一种情况 我需要在 C 目录中创建一个文件夹 并在该文件夹中创建我通过 selenium Web 驱动程序代码拍摄的屏幕截图 它需要存储在带有时间戳的文件夹中 如果我每天按计划运行脚本 所有屏幕截
  • 如何默认将 Maven 插件附加到阶段?

    我有一个 Maven 插件应该在编译阶段运行 所以在项目中consumes我的插件 我必须做这样的事情
  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • Android MediaExtractor seek() 对 MP3 音频文件的准确性

    我在使用 Android 时无法在eek 上获得合理的准确度MediaExtractor 对于某些文件 例如this one http www archive org download emma solo librivox emma 01
  • 加速代码 - 3D 数组

    我正在尝试提高我编写的一些代码的速度 我想知道从 3d 整数数组访问数据的效率如何 我有一个数组 int cube new int 10 10 10 我用价值观填充其中 然后我访问这些值数千次 我想知道 由于理论上所有 3d 数组都存储在内
  • 控制Android的前置LED灯

    我试图在用户按下某个按钮时在前面的 LED 上实现 1 秒红色闪烁 但我很难找到有关如何访问和使用前置 LED 的文档 教程甚至代码示例 我的意思是位于 自拍 相机和触摸屏附近的 LED 我已经看到了使用手电筒和相机类 已弃用 的示例 但我
  • 操作错误不会显示在 JSP 上

    我尝试在 Action 类中添加操作错误并将其打印在 JSP 页面上 当发生异常时 它将进入 catch 块并在控制台中打印 插入异常时出错 请联系管理员 在 catch 块中 我添加了它addActionError 我尝试在jsp页面中打
  • Spring Data JPA 应用排序、分页以及 where 子句

    我目前正在使用 Spring JPA 并利用此处所述的排序和分页 如何通过Spring data JPA通过排序和可分页查询数据 https stackoverflow com questions 10527124 how to query
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • 路径中 File.separator 和斜杠之间的区别

    使用有什么区别File separator和一个正常的 在 Java 路径字符串中 与双反斜杠相反 平台独立性似乎不是原因 因为两个版本都可以在 Windows 和 Unix 下运行 public class SlashTest Test
  • Spring @RequestMapping 带有可选参数

    我的控制器在请求映射中存在可选参数的问题 请查看下面的控制器 GetMapping produces MediaType APPLICATION JSON VALUE public ResponseEntity
  • 如何在PreferenceActivity中添加工具栏

    我已经使用首选项创建了应用程序设置 但我注意到 我的 PreferenceActivity 中没有工具栏 如何将工具栏添加到我的 PreferenceActivity 中 My code 我的 pref xml
  • Java TestNG 与跨多个测试的数据驱动测试

    我正在电子商务平台中测试一系列商店 每个商店都有一系列属性 我正在考虑对其进行自动化测试 是否有可能有一个数据提供者在整个测试套件中提供数据 而不仅仅是 TestNG 中的测试 我尝试不使用 testNG xml 文件作为机制 因为这些属性
  • Java Integer CompareTo() - 为什么使用比较与减法?

    我发现java lang Integer实施compareTo方法如下 public int compareTo Integer anotherInteger int thisVal this value int anotherVal an
  • 如何从终端运行处理应用程序

    我目前正在使用加工 http processing org对于一个小项目 但是我不喜欢它附带的文本编辑器 我使用 vim 编写所有代码 我找到了 pde 文件的位置 并且我一直在从 vim 中编辑它们 然后重新打开它们并运行它们 重新加载脚
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • 捕获的图像分辨率太大

    我在做什么 我允许用户捕获图像 将其存储到 SD 卡中并上传到服务器 但捕获图像的分辨率为宽度 4608 像素和高度 2592 像素 现在我想要什么 如何在不影响质量的情况下获得小分辨率图像 例如我可以获取或设置捕获的图像分辨率为原始图像分
  • 使用 xpath 和 vtd-xml 以字符串形式获取元素的子节点和文本

    这是我的 XML 的一部分

随机推荐

  • java实现kafka消息发送和接收

    之前写了一篇关于kafka集群搭建的点击打开链接 想了解的可以看下 今天这个实现是和前面集群对应的 使用的是新版的API 属性如果想定制自己的 需要到官方网址上面去查看一下对应的值 推介大家多去看看官方的介绍和demo 网上有些翻译过来的例
  • 这可能是史上最详细的MES介绍

    本文篇幅较长 干货满满 可以先收藏 方便日后再次查看 目录 MES 的定义 MES 的产生背景 MES 的发展历程 MES 的功能介绍 MES 与其他 IT 系统的关系 MES 的业务价值 MES 的定义 MES Manufacturing
  • 关于webconfig 的配置跨域和理解

    今日碰到一个问题 就是在很久以前碰到的跨域问题 需求 页面要显示1个图片 但是因为各种原因 导致图片在服务器2上 但是要展示的程序在服务器1 的上面 这样就造成了在显示的时候出现了跨域的问题 本来的思路为直接写个程序进行后台获得图片的路径
  • DROP DATABASE

    在做迁移时 由于某种原因导致回退 现在准备将备库的数据库删除 然后重新部署dg 但在删除备库的时候遇到一些小问题 在节点一执行 oracle sde1 sqlplus as sysdba SQL Plus Release 11 2 0 3
  • Vmware安装到本地,磁盘不够解决方案

    在使用虚拟机的时候 如果在创建的时候选择错误的盘符 那么在安装虚拟机后这个盘符的空间容量不够的问题 那么如何把虚拟机迁移出来到另外的盘符 1 找到虚拟机安装路径 打开虚拟机点击虚拟机详细信息 查看详细的虚拟机的路径 2 找到虚拟机所有的文件
  • 小程序web-view,h5页监听返回到小程序指定页面

    在h5页面进行监听返回跳转判断 created this pushHistory window addEventListener popstate function e 首页点击返回 直接关闭网页 WeixinJSBridge call c
  • QT定时器与lambda表达式联合使用

    QTimer定时器在程序开发中经常使用 比如网络请求超时检查 定时刷新数据 控制动态图开始停止等功能 一般如果是定时触发某个标志 用专来的槽函数处理会显示有点繁琐 如果用lambda表达式处理就不用专门声明定义槽函数 这样代码会更简洁 下面
  • 在Eclipse中安装JSHint插件

    离线安装 1 下载插件包 http download eclipsesource com rsternberg jshint eclipse 0 9 8 20130728 0004 b94b446 zip 2 解压缩后是一个jshint e
  • Linux 自定义简单命令

    如何让一个脚本文件没有 sh后缀输入文件名即可执行 权限问题 首先当然得让它成为可执行文件 不要出现死亡Permission denine 执行以下命令 chmod x 文件路径 文件名 两种方式 当我们输入一个命令的时候默认是从下面这些路
  • 利用Python中的statsmodels简单建立多元线性回归模型(一)

    利用Python中的statsmodels简单建立多元线性回归模型 一 概念简单介绍 多元线性回归其实是在一元线性回归的基础上增加了若干个自变量个数 数学表达式如下 其中 y y y是因变量 响应变量 0
  • ESOE-IDE v0.3 技术说明书

    ESOE IDE v0 3 技术说明书 Author Feng WeiGuo 冯卫国 Email forxm 21cn com Web http www supertree org Tel 86 0755 81030955 All Righ
  • 如何获取股票预测数据集“上海证券综合指数”(上证综指,Shanghai Composite Index)?

    以下网址可提供较为全面的数据集 涵盖Date Opening price Highest price Lowest price Closing price Volume Turnover Ups and Downs Change指标 即日期
  • 10分钟教你用Python玩转微信之抓取好友个性签名制作词云

    01 前言 展示 各位小伙伴我又来啦 今天带大家玩点好玩的东西 用Python抓取我们的微信好友个性签名 然后制作词云 怎样 有趣吧 好了 下面开始干活 我知道你们还是想先看看效果的 后台登录 词云 02 环境准备 Python版本 3 6
  • Linux基础笔记18

    fdisk 分区工具 fdisk 这个古老的软件并不认识 GPT 所以 fdisk 只支持 MBR 的分区模式 且磁盘小于2T 大于了就不能使用 fdisk 进行分区了 新磁盘的分区 一块新加的磁盘的分区方式 检查系统中需要分区的磁盘 fd
  • Vue:Vue动画效果全解析

    Vue中的CSS动画原理 当使用transition 标签包裹标签时 Vue会自动分析其css样式 从而构建动画流程 下图中的点的开头到结尾即为一个动画流程 当一个动画流程执行时 内部被transition 标签包裹的标签瞬间增加两个fad
  • 深度之眼Paper带读笔记NLP.12:层次化attention网络.Baseline.09

    文章目录 前言 第一课 论文导读 文本分类 文本挖掘 数据类型 文本分类 相关技术 基于深度学习的文本分类 baseline涉及的三篇TC的论文 分层注意网络 前期知识储备 第二课论文精读 论文背景 论文整体框架 论文标题 层次注意力网络
  • Postman的高级用法一:重新认识postman核心模块

    本请求示例来自于免费天气API 实况天气接口API开发指南 未来一天天气预报api 天气API 关于Postman的核心模块 全局变量 请求接口 请求体 预处理脚本 测试用例模块 测试者可以针对请求响应做测试 编写测试用例 请求响应 测试用
  • webpack基础配置

    直接上代码 const path require path 为html文件中引入的外部资源如script link动态添加每次compile后的hash 防止引用缓存的外部文件问题 可以生成创建html入口文件 比如单页面可以生成一个htm
  • MYSQL数据库(七)MySQL架构和性能优化

    成功不易 加倍努力 MySQL架构和性能优化 4 1 存储引擎 4 1 1 MyISAM存储引擎 4 1 2 InnoDB引擎 4 1 3 其它存储引擎 4 1 4 管理存储引擎 4 2 MySQL中的系统数据库 4 3 服务器配置和状态
  • 数据结构与算法(二):线性表

    一 基本概念 二 顺序表 三 链表 1 单向链表 2 单向循环链表 3 双向链表 4 静态链表 上一篇 数据结构与算法 一 概述 中介绍了数据结构的一些基本概念 并分别举例说明了算法的时间复杂度和空间复杂度的求解方法 这一篇主要介绍线性表