数据结构(JS实现)

目录

  • 链表
    • 链表的特点
    • 链表中的常见操作
    • 单链表
      • append(data)尾部追加新节点
      • toString()输出链表的节点数据
      • 插入节点insert(position,data)
      • get(position)获取链表指定位置节点的数据
      • indexOf(data)查找对应数据节点的位置
      • update(position, newData)更新指定位置节点数据
      • removeAt(position)删除指定位置的节点
      • remove(data)删除第一个数据为data的节点
      • isEmpty()判断链表是否为空
      • size()返回链表长度
      • 单链表构造函数完整实现
    • 经典相关算法题
      • 链表反转
  • 数组
  • 哈希表/散列表
    • 完美二叉树(Perfect Binary Tree)/满二叉树(Full Binary Tree)
    • 完全二叉树(Compelete Binary Tree)
    • 二叉搜索树/二叉查找树/二叉排序树(Binary Search Tree,简称BST)

链表

与数组不同,我们无法在常量时间内访问单链表中的随机元素。 如果我们想要获得第 i 个元素,我们必须从头结点逐个遍历。 我们按索引来访问元素平均要花费 O(N) 时间,其中 N 是链表的长度。

  • 查找时间复杂度:O(n)

创建单向链表类

// 封装链表的构造函数
function LinkedList() {
    //封装一个Node类,用于保存每个节点信息
    function Node(data,next) {
        this.data = data
        this.next = (next===undefined ? null : next)
    }
    // 链表中的属性
    this.length = 0 // 链表的长度
    this.head = null //链表的第一个节点
}

ES6

class LinkedList{
	constructor Node(data,next) {
        this.data = data
        this.next = (next===undefined ? null : next)
        // 链表中的属性
    	this.length = 0 // 链表的长度
    	this.head = null //链表的第一个节点
    }
}

链表的特点

链表和数组一样,可以用于存储一系列的元素,但是链表和数组的实现机制完全不同。链表的每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(有的语言称为指针或连接)组成。类似于火车头,一节车厢载着乘客(数据),通过节点连接另一节车厢。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • head属性指向链表的第一个节点;
  • 链表中的最后一个节点指向null;
  • 当链表中一个节点也没有的时候,head直接指向null;

数组存在的缺点:
数组的创建通常需要申请一段连续的内存空间(一整块内存),并且大小是固定的。所以当原数组不能满足容量需求时,需要扩容(一般情况下是申请一个更大的数组,比如2倍,然后将原数组中的元素复制过去)。
在数组的开头或中间位置插入数据的成本很高,需要进行大量元素的位移。

链表的优势:
链表中的元素在内存中不必是连续的空间,可以充分利用计算机的内存,实现灵活的内存动态管理。
链表不必在创建时就确定大小,并且大小可以无限地延伸下去。
链表在插入和删除数据时,时间复杂度可以达到O(1),相对数组效率高很多。

链表的缺点:
链表访问任何一个位置的元素时,都需要从头开始访问(无法跳过第一个元素访问任何一个元素)。
无法通过下标值直接访问元素,需要从头开始一个个访问,直到找到对应的元素。
虽然可以轻松地到达下一个节点,但是回到前一个节点是很难的(单链表比较困难,双链表简单)。

链表中的常见操作

函数名是自定义的
append(element):向链表尾部添加一个新的项;
insert(position,element):向链表的特定位置插入一个新的项;
get(position):获取对应位置的元素;
indexOf(element):返回元素在链表中的索引。如果链表中没有该元素就返回-1;
update(position,element):修改某个位置的元素;
removeAt(position):从链表的特定位置移除一项;
remove(element):从链表中移除一项;
isEmpty():如果链表中不包含任何元素,返回trun,如果链表长度大于0则返回false;
size():返回链表包含的元素个数,与数组的length属性类似;
toString():由于链表项使用了Node类,就需要重写继承自JavaScript对象默认的toString方法,让其只输出元素的值;

单链表

append(data)尾部追加新节点

// 封装链表的构造函数
function LinkedList() {
    //封装一个Node类,用于保存每个节点信息
    function Node(data,next) {
        this.data = data
        this.next = (next===undefined ? null : next)
    }
    // 链表中的属性
    this.length = 0 // 链表的长度
    this.head = null //链表的第一个节点
    //链表中的方法
    // 1.追加节点的方法append,追加是指在链表的末尾添加节点
    LinkedList.prototype.append = function (data) {
        // 首先创建节点
        let newNode = new Node(data)
        // 然后找到末尾的节点,将新创建的节点添加到末尾
        // 如果是空链,直接让头指针指向新节点
        if (this.length == 0) {
            this.head = newNode
        } else {
            // 从头开始查找,用current标记当前查找的位置
            let current = this.head
            // if(current==null) current=newNode // 也可以这样判断链表目前是否是空链
            // 否则查找链表的最后一个节点
            while (current.next) {
                current = current.next
            }
            // 最后一个节点的current.next==null,所以会跳出while循环
            // 让最后一个节点指向新节点
            current.next = newNode
        }
        // 链表长度加一
        this.length += 1
    }
}

过程详解:

  1. 首先让current指向第一个节点:
    在这里插入图片描述
  2. 通过while循环使current指向最后一个节点,最后通过current.next = newNode,让最后一个节点指向新节点newNode
    在这里插入图片描述
    测试代码
    //测试代码
    //1.创建LinkedList
    let list = new LinkedList()
    
    //2.测试append方法
    list.append('aaa')
    list.append('bbb')
    list.append('ccc')
    console.log(list);  

结果
在这里插入图片描述

toString()输出链表的节点数据

代码实现:

LinkedList.prototype.toString =function(){
    let current=this.head
    // listString存储链表的节点数据
    let listString=''
    // 空链表不会进入该循环,content为空
    while(current){
        listString += current.data+' '// 每个节点数据后加个空格,便于阅读
        current=current.next
    }
    return listString
}

测试代码

    //测试代码
    //1.创建LinkedList
    let list = new LinkedList()
    
    //2.插入数据
    list.append('aaa')
    list.append('bbb')
    list.append('ccc')
    
    //3.测试toString方法
    console.log(list.toString());

结果
在这里插入图片描述

插入节点insert(position,data)

代码

            // position的有效范围是整数[0,length]
            LinkedList.prototype.insert=function(position,data){
                let newNode=new Node(data)
                if(position<0|| position>=this.length){
                    // false表示插入失败
                    return false;
                }else if(position==0){//newNode成为头结点的情况
                    // 注意顺序不能颠倒
                    newNode.next=this.head
                    this.head=newNode
                }else{
                    // 包含newNode成为最后一个节点的情况,与插入在中间位置一样的操作
                    let current=this.head
                    // 找到newNode要插入位置的前一个节点,跳出循环后current指向该节点
                    for(let i=0;i<position;i++){
                        current=current.next
                    }
                    // 顺序不能颠倒
                    newNode.next=current.next
                    current.next=newNode
                }
                this.length+=1
                // true表示插入成功
                return true
            }

过程详解:
position是节点插入链表后所处的位置,其有效范围是整数[0,length],根据插入节点位置的不同可分为多种情况:
情况1:position = 0:
通过: newNode.next = this.head,建立连接1;
通过: this.head = newNode,建立连接2;(不能先建立连接2,否则this.head不再指向Node1)
image-20200306103312580
情况2:position > 0:
在这里插入图片描述

                    // 包含newNode成为最后一个节点的情况,与插入在中间位置一样的操作
                    let current=this.head
                    // 找到newNode要插入位置的前一个节点,跳出循环后current指向该节点
                    for(let i=0;i<position;i++){
                        current=current.next
                    }
                    // 顺序不能颠倒
                    newNode.next=current.next
                    current.next=newNode

测试代码

    //1.创建LinkedList
    let list = new LinkedList()
    
    //2.插入数据
    list.append('aaa')
    list.append('bbb')
    list.append('ccc')
    
    //3.测试insert方法
    list.insert(0, '在链表最前面插入节点');
    list.insert(2, '在链表中第二个节点后插入节点');
    list.insert(5, '在链表最后插入节点');
    alert(list)// alert会自动调用参数的toString方法
    console.log(list);

结果
在这里插入图片描述
在这里插入图片描述

get(position)获取链表指定位置节点的数据

	//测试代码
    //1.创建LinkedList
    let list = new LinkedList()
    
    //2.插入数据
    list.append('aaa')
    list.append('bbb')
    list.append('ccc')	

	//3.测试get方法
    console.log(list.get(0));
    console.log(list.get(1));

在这里插入图片描述

indexOf(data)查找对应数据节点的位置

代码

// 根据数据查询数据所在链表位置
LinkedList.prototype.indexOf=function(data){
    let current= this.head
    let index=0
    // 从头结点开始逐个查找数据等于data的节点
    while(current){
        if(current.data==data){
            return index
        }
        current=current.next
        index+=1
    }
    // 没有查找到就返回-1
    return -1
}

测试代码

	//测试代码
    //1.创建LinkedList
    let list = new LinkedList()
    
    //2.插入数据
    list.append('aaa')
    list.append('bbb')
    list.append('ccc')	
    
    //3.测试indexOf方法
    console.log(list.indexOf('aaa'));
    console.log(list.indexOf('ccc'));

测试结果
在这里插入图片描述

update(position, newData)更新指定位置节点数据

代码

LinkedList.prototype.update=function(position,newData){
    // position有效取值是[0,this.length-1]间的整数,修改失败返回false
    if(position<0|| position>=this.length) return false;
    let current=this.head
    let i=0
    // 遍历至处于position位置的节点
    while(i++<position){
        current=current.next
    }
    // console.log(i); //position=2时,i=3,说明跳出循环i还是会自增1,因为自增运算符比比较运算符优先级高
    // 跳出循环时,current已经指向处于position位置的节点
    current.data=newData
    return true
}

测试代码

	//1.创建LinkedList
    let list = new LinkedList()
    
    //2.插入数据
    list.append('aaa')
    list.append('bbb')
    list.append('ccc')	
    
    //3.测试update方法
    console.log(list.update(0, '修改第0个节点'))
    console.log(list.update(2, '修改第2个节点'))
    console.log(list.update(3, '超出范围无法修改'));
    console.log(list.toString());

测试结果
在这里插入图片描述

removeAt(position)删除指定位置的节点

情况1:position = 0,即移除第一个节点(Node1)。通过:this.head = this.head.next,改变指向1即可;虽然Node1的next仍指向Node2,但是没有引用指向Node1,则Node1会被垃圾回收器自动回收,所以不用处理Node1指向Node2的引用next。
在这里插入图片描述
情况2:positon > 0,比如pos = 2即移除第三个节点(Node3)。
首先,定义两个变量previous和curent分别指向需要删除位置pos = x的前一个节点和当前要删除的节点;
然后,通过:previous.next = current.next,改变指向1即可;
随后,没有引用指向Node3,Node3就会被自动回收,至此成功删除Node3 。
在这里插入图片描述
代码

            LinkedList.prototype.removeAt=function(position){
                // 超出范围的删除不了
                if(position<0|| position>=this.length) return false;
                let current =this.head
                // 如果删除第一个节点
                if(position==0){
                    this.head=this.head.next
                }else{
                    let i=0;
                    let previous=this.head
                    while(i++<position){
                        previous=current
                        current=current.next
                    }
                    previous.next=current.next
                    this.length--;
                }
                return current.data
            }

测试代码

    let list = new LinkedList()
    
    //2.插入数据
    list.append('aaa')
    list.append('bbb')
    list.append('ccc')
  
  //3.测试removeAt方法
    console.log(list.removeAt(0));
    console.log(list.removeAt(1));
    console.log(list);

测试结果
在这里插入图片描述

remove(data)删除第一个数据为data的节点

LinkedList.prototype.remove=function(data){
    let current= this.head
    let index=0
    let previous=this.head
    // 从头结点开始逐个查找数据等于data的节点
    while(current){
        if(current.data==data){
            // 如果删除的是头节点
            if(index==0){
                this.head=this.head.next
            }else{
                previous.next=current.next
            }
            this.length--;
            return index
        }
        // previous和current指向下一个节点
        previous=current
        current=current.next
        index+=1
    }
    // 没有查找到就返回false
    return false
}

测试代码

    let list = new LinkedList()
    
    //2.插入数据
    list.append('aaa')
    list.append('bbb')
    list.append('ccc')

/*---------------其他方法测试----------------*/
  	//remove方法
  	console.log(list.remove('aaa'));
  	console.log(list)

结果
在这里插入图片描述

isEmpty()判断链表是否为空

代码

// 判断链表是否为空
LinkedList.prototype.isEmpty=function(){
    return this.length==0
}

size()返回链表长度

代码

// 返回链表的长度
LinkedList.prototype.size=function(){
    return this.length
}

测试代码

    let list = new LinkedList()
    
    //2.插入数据
    list.append('aaa')
    list.append('bbb')
    list.append('ccc')

/*---------------其他方法测试----------------*/
  	//remove方法
  	console.log(list.isEmpty());
    console.log(list.size())

结果
在这里插入图片描述

单链表构造函数完整实现

        // 封装链表的构造函数
        function LinkedList() {
            //封装一个Node类,用于保存每个节点信息
            function Node(data) {
                this.data = data
                this.next = null
            }
            // 链表中的属性
            this.length = 0 // 链表的长度
            this.head = null //链表的第一个节点
            //链表中的方法
            // 1.追加节点的方法append,追加是指在链表的末尾添加节点
            LinkedList.prototype.append = function (data) {
                // 首先创建节点
                let newNode = new Node(data)
                // 然后找到末尾的节点,将新创建的节点添加到末尾
                // 如果是空链,直接让头指针指向新节点
                if (this.length == 0) {
                    this.head = newNode
                } else {
                    // 从头开始查找,用current标记当前查找的位置
                    let current = this.head
                    // if(current==null) current=newNode // 也可以这样判断链表目前是否是空链
                    // 否则查找链表的最后一个节点
                    while (current.next) {
                        current = current.next
                    }
                    // 最后一个节点的current.next==null,所以会跳出while循环
                    // 让最后一个节点指向新节点
                    current.next = newNode
                }
                // 链表长度加一
                this.length += 1
            }
            // 2.返回链表各个节点的内容的方法
            LinkedList.prototype.toString = function () {
                let current = this.head
                let content = ''
                // 空链表不会进入该循环,content为空
                while (current) {
                    content += current.data + ' '// 每个节点数据后加个空格,便于阅读
                    current = current.next
                }
                return content
            }
            // position的有效范围是整数[0,length-1]
            LinkedList.prototype.insert=function(position,data){
                let newNode=new Node(data)
                if(position<0|| position>this.length){
                    // false表示插入失败
                    return false;
                }else if(position==0){//newNode成为头结点的情况
                    // 注意顺序不能颠倒
                    newNode.next=this.head
                    this.head=newNode
                }else{
                    // 包含newNode成为最后一个节点的情况,与插入在中间位置一样的操作
                    let current=this.head
                    // 找到newNode要插入位置的前一个节点,跳出循环后current指向该节点
                    for(let i=0;i<position-1;i++){
                        current=current.next
                    }
                    // 顺序不能颠倒
                    newNode.next=current.next
                    current.next=newNode
                }
                this.length+=1
                // true表示插入成功
                return true
            }
            LinkedList.prototype.get=function(position){
                // position有效取值是[0,this.length-1]间的整数
                if(position<0|| position>=this.length) return null;
                let current=this.head
                let i=0
                // 遍历至处于position位置的节点
                while(i++<position){
                    current=current.next
                }
                // console.log(i); //position=2时,i=3,说明跳出循环i还是会自增1,因为自增运算符比比较运算符优先级高
                // 跳出循环时,current已经指向处于position位置的节点
                return current.data    
            }
            // 根据数据查询数据所在链表位置
            LinkedList.prototype.indexOf=function(data){
                let current= this.head
                let index=0
                // 从头结点开始逐个查找数据等于data的节点
                while(current){
                    if(current.data==data){
                        return index
                    }
                    current=current.next
                    index+=1
                }
                // 没有查找到就返回-1
                return -1
            }

            LinkedList.prototype.update=function(position,newData){
                // position有效取值是[0,this.length-1]间的整数,修改失败返回false
                if(position<0|| position>=this.length) return false;
                let current=this.head
                let i=0
                // 遍历至处于position位置的节点
                while(i++<position){
                    current=current.next
                }
                // console.log(i); //position=2时,i=3,说明跳出循环i还是会自增1,因为自增运算符比比较运算符优先级高
                // 跳出循环时,current已经指向处于position位置的节点
                current.data=newData
                return true
            }
            LinkedList.prototype.removeAt=function(position){
                // 超出范围的删除不了
                if(position<0|| position>=this.length) return false;
                let current =this.head
                // 如果删除第一个节点
                if(position==0){
                    // 在JS中,垃圾回收机制会清理未被指向的对象
                    this.head=this.head.next
                }else{
                    let i=0;
                    let previous=this.head
                    while(i++<position){
                        previous=current
                        current=current.next
                    }
                    // 在JS中,垃圾回收机制会清理未被指向的对象
                    previous.next=current.next
                }
                this.length--;
                return current.data
            }
            LinkedList.prototype.remove=function(data){
                let current= this.head
                let index=0
                let previous=this.head
                // 从头结点开始逐个查找数据等于data的节点
                while(current){
                    if(current.data==data){
                        // 如果删除的是头节点
                        if(index==0){
                            this.head=this.head.next
                        }else{
                            previous.next=current.next
                        }
                        this.length--;
                        return index
                    }
                    // previous和current指向下一个节点
                    previous=current
                    current=current.next
                    index+=1
                }
                // 没有查找到就返回false
                return false
            }
            // 判断链表是否为空
            LinkedList.prototype.isEmpty=function(){
                return this.length==0
            }
            // 返回链表的长度
            LinkedList.prototype.size=function(){
                return this.length
            }
        }

链表节点实现
Java

// Definition for singly-linked list.
public class SinglyListNode {
    int val;
    SinglyListNode next;
    SinglyListNode(int x) { val = x; }
}

C++

// Definition for singly-linked list.
struct SinglyListNode {
    int val;
    SinglyListNode *next;
    SinglyListNode(int x) : val(x), next(NULL) {}
};

JS

//封装一个Node类,用于保存每个节点信息
function Node(element){
	this.element=element
	this.next=null
}

经典相关算法题

链表反转

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表
示例 1:
在这里插入图片描述
示例2
在这里插入图片描述
示例3
空链表反转后仍为空
题解

  1. 遍历节点,将每个节点的指向反转
/**
 * 定义单链表节点
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */

var reverseList = function(head) {
	// cur指向当前遍历的节点,pre指向前一个节点,
    let next=undefined,pre=null,cur=head;
    while(cur){
    	// 顺序不能颠倒
    	// next存储当前遍历节点的下一个结点的引用
        next=cur.next
        // 反转指向
        cur.next=pre
        // pre指向后移一位
        pre=cur;
        // cur指向后移一位
        cur=next
    }
    // 最终的pre成为新的头指针
    head=pre
    return head
};

复杂度分析
时间复杂度:O(n),其中 n 是链表的长度。需要遍历链表一次。
空间复杂度:O(1)

  1. 递归
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var reverseList = function(head) {
    let pre=head,cur=head.next;
    // 考虑空链表和只有一个节点的情况
    if(pre==null || cur==null){
        head.next=null
        return pre
    };
    cur.next=pre
    return reverseList(cur)// 此时cur就相当于head
};

数组

  • 查找时间复杂度:O(1),因为可以直接根据索引查找
  • 插入或删除时间复杂度O(n),因为要移动删除或插入位置后面的数组元素

哈希表/散列表

用哈希函数确定键的存储位置
特点

  • 键不一样相应的存储位置也不一样
  • 键相同得到的存储位置相同
    在这里插入图片描述

因为所有树都可以转换成二叉树的形式,所以这里就只介绍二叉树数据结构的实现方式

完美二叉树(Perfect Binary Tree)/满二叉树(Full Binary Tree)

完全二叉树(Compelete Binary Tree)

二叉搜索树/二叉查找树/二叉排序树(Binary Search Tree,简称BST)

二叉搜索树构造函数实现如下

        function BinarySearchTree(){
            this.root=null
            // 节点构造函数
            function Node(key){
                this.key=key
                this.left=null
                this.right=null
            }
        }

二叉搜索树的常见操作:
insert(key):向树中插入一个新的键;
search(key):在树中查找一个键,如果节点存在,则返回true;如果不存在,则返回false;
inOrderTraverse:通过中序遍历方式遍历所有节点;
preOrderTraverse:通过先序遍历方式遍历所有节点;
postOrderTraverse:通过后序遍历方式遍历所有节点;
min:返回树中最小的值/键;
max:返回树中最大的值/键;
remove(key):从树中移除某个键;

按照这个算法,在相同的顺序下最终所形成的二叉搜索树应该是一样的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/296552.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在 wsl 中运用 kubeconfig 实现自由管理 kubernetes 集群

本文来自我的博客地址 文章目录 k8s 集群配置理解 kubeconfig思路整理:在 wsl 上安装 kubectl配置自动补全 拷贝 kubeconfig登到 k8s 集群的 master 节点, 把 kubeconfig 拷贝到 wsl测试 kubectl k8s 集群配置 IPHost配置11.0.1.150master1 (keepalivedhaproxy)2C 4G 30G11.0.…

git本地创建分支并推送到远程关联起来

git本地创建分支并推送到远程关联起来 git本地基于当前分支创建个新的分支&#xff0c;然后推送到远程&#xff0c;并把本地新创建的分支和远程分支关联 在当前分支下&#xff0c;新建分支 git checkout -b test推送到远程仓库 git push origin test将本地分支和远程分支关联…

2015年电赛控制类—STM32风力摆控制系统资料+源程序

目录 一、项目背景 二、主要研究内容 三、总体思路与研究方案 四、主要研究结果 五、程序 六、图片 一、项目背景 风力摆控制系统是一种利用风力控制物体做简谐运动的系统&#xff0c;风力的利用和控制技术在我国的发展尚未完善&#xff0c;国内正处于起步阶段。风力摆的…

免费的GPT4来了,你还不知道吗?

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…

SSM实现的校园门户平台网站系统----计算机毕业设计

项目介绍 本系统为前后台项目&#xff0c;后台为管理员登录&#xff0c;前台为社团、学生、教师角色登录&#xff1b; 管理员角色包含以下功能&#xff1a; 管理员登录,角色管理,权限管理,社团管理,教师管理,学生管理,公告管理,新闻管理,校园风采管理,求职招聘管理,校历管理…

RabbitMQ快速入门(详细)

RabbitMQ 消息中间件/消息队列 1、消息中间件 1、简介 **消息中间件也可以称消息队列&#xff0c;是指用高效可靠的消息传递机制进行与平台无关的数据交流&#xff0c;并基于数据通信来进行分布式系统的集成。**通过提供消息传递和消息队列模型&#xff0c;可以在分布式环境…

Linux——系统安全及应用

一、基本安全措施 1、系统账号清理 常见的非登录用户账号包括bin、daemon、 adm、lp、mail等。为了确保系统安全&#xff0c;这些用户账号的登录Shell通常是/ sbin/nologin&#xff0c;表示禁止终端登录&#xff0c;应确保不被人为改动。 //将非登陆用户的Shell设为/sbin/nolo…

文献综述 AI 应用对比 — Elicit, GPTs 与 Perplexity

&#xff08;注&#xff1a;本文为小报童精选文章&#xff0c;已订阅小报童或加入知识星球「玉树芝兰」用户请勿重复付费&#xff09; 通过我的这些尝试&#xff0c;你无需再自己去摸索&#xff0c;可以直接根据我展示的结果选择合适的工具&#xff0c;更有效地进行文献回顾。 …

抖店怎么上架商品?

我是电商珠珠 没有货源的商家&#xff0c;上架商品其实很简单&#xff0c;只需要找到工具去采集链接上架即可。但在上架商品的时候也不能完全照搬&#xff0c;需要涉及到主图、详情页、标题和价格的优化&#xff0c;这些都会影响到商品的点击率&#xff0c;所以上架商品的过程…

3元一平方公里的在线卫星影像

我们为大家分享了免费下载卫星影像的方法。 但让人遗憾的是&#xff0c;该影像的最高分辨率只有10米&#xff0c;需要更高清且比较新的卫星影像&#xff0c;看来还是得付费购买才比较靠谱。 自助选择区县范围 商业卫星影像主要面向企事业单位&#xff0c;一般来讲都比较贵&a…

每周一算法:倍增法求区间最大最小值(RMQ)

RMQ RMQ 是英文 Range Maximum/Minimum Query 的缩写&#xff0c;表示区间最大&#xff08;最小&#xff09;值。使用倍增思想解决 RMQ 问题的方法是 ST 表&#xff08;Sparse Table&#xff0c; 稀疏表 &#xff09;。ST 表是用于解决 可重复贡献问题 的数据结构。 可重复贡献…

PHP语言B/S架构医院(安全)不良事件上报系统源码

医院安全&#xff08;不良&#xff09;事件上报系统采用无责的、自愿的填报不良事件方式&#xff0c;有效地减轻医护人员的思想压力&#xff0c;实现以事件为主要对象&#xff0c;可以自动、及时、实际地反应医院的安全、不良、近失事件的情况&#xff0c;更好地掌握不良事件的…

Linux学习记录——삼십오 传输层UDP协议

文章目录 1、端口号2、UDP协议 信息加上应用层报头后&#xff0c;下一步发送到传输层 1、端口号 端口号标识了一个主机上进行通信的唯一一个应用程序。 在TCP/IP协议中&#xff0c;通过源IP&#xff0c;源端口号&#xff0c;目的IP&#xff0c;目的端口号&#xff0c;协议号来…

静态网页设计——红旗汽车官网(HTML+CSS+JavaScript)

前言 声明&#xff1a;该文章只是做技术分享&#xff0c;若侵权请联系我删除。&#xff01;&#xff01; 感谢大佬的视频&#xff1a; https://www.bilibili.com/video/BV1gK411x7Bg/?vd_source5f425e0074a7f92921f53ab87712357b 使用技术&#xff1a;HTMLCSSJS&#xff08;…

Maven(mvn)的学习下载和配置

文章目录 Maven&#xff08;mvn&#xff09;1.Maven 是什么&#xff1f;2.Maven做什么&#xff1f;2.1传统方式对项目的管理2.2Maven对jar包的管理 3.Maven怎么学3.1Maven如何创建项目3.2Maven的下载与配置3.3Maven的项目结构3.4Maven依赖的引入3.5Maven依赖的剔除3.6Maven依赖…

【教学类-09-04】20240102《游戏棋N*N》数字填写,制作棋子和骰子

作品展示 背景需求&#xff1a; 最近在清理学具材料库&#xff0c;找到一套1年多前的《N*N游戏棋》&#xff0c;把没有用完的棋盘拿出来&#xff0c;&#xff0c;想给大4班换花样&#xff0c;并把它们用掉。 程序代码在这里 【教学类-09-03】20221120《游戏棋10*10数字如何直接…

GUI三维绘图

绘制三维图plot3 t0:pi/50:10*pi; xsin(t); ycos(t); zt; plot3(x,y,z); 产生栅格数据点meshgrid 这个接口在绘制三维图像里面相当重要&#xff0c;很多时候要将向量变成矩阵才能绘制三维图。 x0:0.5:5; y0:1:10; [X,Y]meshgrid(x,y); plot(X,Y,o); x和y是向量&#xff0c;…

124基于matlab的禁忌搜索算法和蚁群优化算法优化TSP路径

基于matlab的禁忌搜索算法和蚁群优化算法优化TSP路径&#xff0c;动态输出路径规划过程及输出最小距离。数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。需要直接拍下&#xff0c;拍下后发邮箱。标价为程序价格&#xff0c;不包含售后。程序保证可直接运行。 …

1.大数据概述

目录 概述hadoophadoop 模块hadoop 发行版apache社区版本CDP(CDHHDP)其它云产商框架选择 hadoop 安装 结束 概述 先了解几个常用的网站 apache 官网hadoop 官网hadoop githubhttps://github.com/apache/xxx [https://github.com/apache/spark (example)] hadoop hadoop 模块…

Linux内核--进程管理(六)内核进程管理几种CPU调度策略

目录 一、引言 二、CPU调度的直观想法 ------>2.1、FIFO ------>2.2、Priority ------>2.3、调度矛盾 三、各种CPU调度算法 ------>3.1、FCFS(First Come,First Served) ------>3.2、SJF(Short Job First,短作业优先) ------>3.3、RR算法(按时间片…