数据结构

数组Array

  • 数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。

  • 线性表(Linear List)。顾名思义,线性表就是数据排成像一条线一样的结构。每个线性表上的数据最多只有前和后两个方向。其实除了数组,链表、队列、栈等也是线性表结构。

  • 是连续的内存空间和相同类型的数据,它才有了一个堪称“杀手锏”的特性:“随机访问”。但有利就有弊,这两个限制也让数组的很多操作变得非常低效,比如要想在数组中删除、插入一个数据,为了保证连续性,就需要做大量的数据搬移工作。

  • 对于数组来说,存储空间是连续的,所以在加载某个下标的时候可以把以后的几个下标元素也加载到CPU缓存这样执行速度会快于存储空间不连续的链表存储。

<?php
class myClass
{
    private $data;
    private $length;
    private $capacity;

    public function __construct($capacity)
    {
        $capacity = intval($capacity);
        if ($capacity <= 0) return null;

        $this->data     = array();
        $this->capacity = $capacity;
        $this->length   = count($this->data);

    }

    private function checkIfFull($index)
    {
        if ($index>=$this->capacity) {
            return true;
        }
        return false;
    }

    private function checkOutOfRange($index)
    {
        if ($index <= $this->capacity) {
            return true;
        }
        return false;
    }

    public function insert($index, $value)
    {
        $index = intval($index);
        $value = intval($value);
        if ($index < 0) {
            return 1;
        }

        if ($this->checkIfFull($index)) {
            $this->resize(intval(1.5 * $index));
        }


        for ($i = $this->length - 1; $i > $index; $i--) {
            $this->data[$i + 1] = $this->data[$i];
        }

        $this->data[$index] = $value;
        $this->length++;
        return 0;
    }

    public function delete($index)
    {
        $value = 0;
        $index = intval($index);
        if ($index < 0) {
            $code = 1;
            return [$code, $value];
        }

        if ($this->checkOutOfRange($index)) {
            $code = 2;
            return [$code, $value];
        }

        $value = $this->data[$index];
        for ($i = $index; $i < $this->length - 1; $i++) {
            $this->data[$i] = $this->data[$i + 1];
        }
        $this->length--;
        return [0, $value];

    }

    public function find($index)
    {

        $value = 0;
        $index = intval($index);
        if ($index < 0) {
            $code = 1;
            return [$code, $value];
        }
        if ($this->checkOutOfRange($index)) {
            $code = 2;
            return [$code, $value];
        }
        return [0, $this->data[$index]];
    }

    private function resize($capacity)
    {
        $newData = new myClass($capacity);
        for ($i = 0; $i < $this->length; $i++) {
            $newData->data[$i] = $this->data[$i];
        }
        $this->data = $newData->data;
        $this->capacity=$capacity;
    }
}

链表

链表通过指针将一组零散的内存块串联在一起。其中,我们把内存块称为链表的“结点”。为了将所有的结点串起来,每个链表的结点除了存储数据之外,还需要记录链上的下一个结点的地址。如图所示,我们把这个记录下个结点地址的指针叫作后继指针 next。

  • 前面的节点叫前驱节点 后面的节点叫后继节点

跳表

  • 链表加多级索引的结构,就是跳表
  • 跳表中查询任意数据的时间复杂度就是 O(logn)
  • 跳表是通过随机函数来维护平衡性

今天我们讲了跳表这种数据结构。跳表使用空间换时间的设计思路,通过构建多级索引来提高查询的效率,实现了基于链表的“二分查找”。跳表是一种动态数据结构,支持快速地插入、删除、查找操作,时间复杂度都是 O(logn)。跳表的空间复杂度是 O(n)。不过,跳表的实现非常灵活,可以通过改变索引构建策略,有效平衡执行效率和内存消耗。虽然跳表的代码实现并不简单,但是作为一种动态数据结构,比起红黑树来说,实现要简单多了。所以很多时候,我们为了代码的简单、易读,比起红黑树,我们更倾向用跳表。

Trie树:如何实现搜索引擎的搜索关键词提示功能?

概念

  • 字典树,专门处理字符串匹配的数据结构,
  • 用来解决在一组字符串集合快速查找某个字符串的问题。
  • 利用字符串之间的公共前缀,讲重复的前缀合并在一起。
  • Trie 树的本质,就是利用字符串之间的公共前缀,将重复的前缀合并在一起,减少存储空间,提升查询效率。
  • 构建时间复杂度是 O(n)(n 表示所有字符串的长度和) 查询时间复杂度是 O(k)(n 表示要查找的字符串的长度)

实现

  • 构造的每一步,都相当于在Trie树种插入一个字符串
  • 当所有字符串都插入完成,Trie树就构造完毕

适用场景

  • Trie适合前缀查找,比如搜索关键词智能匹配场景、自动输入补全、搜索引擎中的关键词提示功能
  • 精确匹配查找这种问题更适合用散列表或者红黑树来解决
class TrieNode{
    public char data;
    public TrieNode[] children = new TrieNode[26];
    public boolean isEndingChar = false;
    public Integer num = 0;

    public TrieNode(char data) {
        this.data = data;
    }
}
class Trie{
    private TrieNode root=new TrieNode('/');

    public void insert(char[] text){
        TrieNode p = root;
        for (int i = 0; i <text.length ; i++) {
            int index = text[i] - 'a';
            if (p.children[index] == null) {
                p.children[index]=new TrieNode(text[i]);
            }
            p=p.children[index];
            p.num+=1;
        }
        p.isEndingChar=true;
    }

    public boolean find(char[] pattern) {

        TrieNode p = root;
        for (int i = 0; i < pattern.length; i++) {
            int index = pattern[i] - 'a';
            if (p.children[index] == null) {
                return false;
            }
            p = p.children[index];
        }
        if (!p.isEndingChar) return false;
        else return true;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值