数据结构相关知识点(一)

一、线性表

1.什么是线性表?

线性表,全名为线性存储结构。使用线性表存储数据的方式可以理解理解为:把所有数据按照顺序(线性)的存储结构方式,存储在物理空间。

2.线性存储结构

顺序存储结构:数据依次存储在连续的物理空间中(顺序表);

链式存储结构:数据分散存储在不同的物理空间中,通过某种指向关系,来维持它们之间的逻辑关系(链表);

3.顺序表(数组)

        顺序表,就是顺序存储结构,是线性表的一种。顺序表对数据的物理存储结构有明确的要求:顺序表存储数据时,会提前申请一块足够大小的内存,然后将数据依次存储起来,元素的存储空间在内存中是连续存在的。

        优点:1.内存地址连续,数组元素进行遍历时,速度快。

                   2.根据下标,查找指定位置的元素时,速度快。

        缺点:1.长度固定,使用前余姚提前预估长度。

                   2.插入和删除元素时,时间复杂度相对较高。

    时间复杂度:读的时候是  O(1)   插入和删除的时候是O(n)

4.链表

        链表,全名是链式存储结构,也是线性表的一种。链表不限制数据的物理存储位置,使用链表存储的数据元素,其物理存储位置是随机的。由于链表节点之间根本无法体现出各数据之间的逻辑关系。

        链表的组成:

                                数据元素本身,其所在的区域称为数据域;

                                指向直接后继元素的指针,所在的区域称为指针域;

                                

        优点:使用链表结构,不需要提前预估长度,可以克服数组需要预先知道数据长度的缺点

                   链表使用不连续的内存空间,可以充分利用计算机内存空间,实现灵活的内存动态管理

        缺点:链表相比于数组会占用更多的空间,因为他不仅要存储数据本身还需要存储指针域。

                   不能随机的读取元素

                   遍历和查找元素更慢了。

时间复杂度:插入和删除时O(1),遍历查找时O (n); 

链表又有很多种类:单向链表双向链表循环链表双向循环链表。。。

5.链表中常见的问题(判断成环,相交)

判断链表是否有环

Linked.Node node1 = new Linked.Node(1);

Linked.Node node2 = new Linked.Node(2);

Linked.Node node3 = new Linked.Node(3);

Linked.Node node4 = new Linked.Node(4);

Linked.Node node5 = new Linked.Node(5);



node1.next = node2;

node2.next = node3;

node3.next = node4;

node4.next = node5;

node5.next = node3; // 链表产生环
方法一:使用Set集合
private static boolean hasCycle(Node node) {

// 定义Set集合,保存链表中的所有节点

Set<Node> nodeSet = new HashSet<Node>();

// 遍历链表中的每个节点

while(node != null) {

// 判断Set中是否存在该节点

// 如果存在,则代表该链表有环

if(nodeSet.contains(node)) {

return true; // 链表有环

}

// 如果不存在,则将节点加入Set集合,用于后续的判断

nodeSet.add(node);

// 移动链表节点

node = node.next;

}

return false; // 链表无环

}
方法二:快慢指针
private static boolean hasCycle(Node head) {

    if (head == null) {

        return false;

    }



    // 定义快指针和慢指针,从head头节点开始

    Node fast = head;

    Node slow = head;

    while (fast != null && fast.next != null && slow != null) {
    
    fast = fast.next.next; // 快指针移动2步

    slow = slow.next; // 慢指针移动1步



    // 判断fast和slow快慢指针指向的内存地址相同,如果相同,则代表碰面相遇
    
        if (fast == slow) {

        // 如果碰面,就代表链表有环
    
        return true;

        }

    }

    return false;

}

判断是否相交

方法一:使用双重循环判断
public static boolean isIntersect1(Linked link1, Linked link2) {

    for (Node p = link1.first; p != null; p = p.next) {

        for (Node q = link2.first; q != null; q = q.next) {

            if (p == q) {

                return true;

            }

        }

    }

    return false;

}
方法二:使用双指针判断
public static boolean isIntersect2(Linked link1, Linked link2) {
    // 安全检测
    if (link1 == null || link2 == null) {
        return false;
    }

    // p 指向长链表的第一个结点
    // q 指向短链表的第一个结点
    Node p = link1.size() > link2.size() ? link1.first : link2.first;
    Node q = link1.size() > link2.size() ? link2.first : link1.first;

    // 求两个链表长度差
    int diff = Math.abs(link1.size() - link2.size());

    // p先往后移动diff个结点
    while (diff-- > 0) {
        p = p.next;
    }

    // p 和 q 同时往后移动
    while (p != q) {
        p = p.next;
        q = q.next;
    }

    // 如果p(q)不为null,则两个链表相交,否则不相交
    if (p != null) {
        return true;
    } else {
        return false;
    }
}

栈&队列

1.栈

什么是栈

        栈(stack)是一种特殊的线性数据集合,只允许在栈顶top进行加入数据(push)贺移动数据(pop),按照后进先出LIFO的规则进行操作,也可以理解为先入后出FILO;

        栈的实现方式:

                栈的实现结构可以是一维数组或链表来实现,用数组实现的栈叫作顺序栈 ,用链表实现的栈叫作链式栈 。在Java中,顺序栈使用java.util.Stack类实现,链式栈使用java.util.LinkedList类实现。

                时间复杂度:访问指定元素:O(n)                入栈和出栈:O(1)

栈的常见操作

入栈:入栈操作就是把虚拟的元素放入栈中,只允许从栈顶一侧放入元素,新元素将会成为栈顶。

出栈:出栈操作就是把元素从栈中弹出,只有栈顶元素才允许出栈,出栈元素的前一个元素将会成为新的栈顶。

队列

队列是一种线性数据节后,特点类似:行驶车辆的单向隧道

队列中的元素按照先入先出的规则操作

队列的出口端叫做队头,队列的入口端叫做队尾

队列只允许在队头进行出队poll操作(删除

队列只允许在队尾进行入队offer操作(添加

实现方式

数组实现的队列叫作顺序队列
链表实现的队列叫作链式队列

时间复杂度

假设队列中有n个元素。
●访问指定元素的时间复杂度是O(n):最坏情况下,遍历整个队列
●插入删除元素的时间复杂度是O(1):只需要操作队头或队尾元素

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值