javaScript的数据结构与算法/js算法

这篇博客详细介绍了如何使用JavaScript实现常见数据结构,包括栈、队列、单向链表、双向链表、哈希表以及二叉搜索树。提供了详细的代码示例,涵盖了这些数据结构的基本操作,如入栈、出栈、入队、出队、插入、删除、查找等。此外,还展示了如何实现哈希表的扩容和二叉搜索树的遍历。这些内容对于理解数据结构和算法在实际编程中的应用非常有帮助。
摘要由CSDN通过智能技术生成

个人力扣刷题答案,使用js解题

GitHub - ispaomoya/suanfa: 力扣js算法草稿

持续更新哈

目录

一、栈

二、队列

2.1 基本使用

2.2 优先队列

三、链表

3.1 单向链表

3.2 双向链表

四、哈希表

五、合集

六、二叉树

6.1 二叉搜索树


一、栈

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>栈</title>
</head>
<body>
    <script>
        //封装栈类
        function Stack() {
            //栈的属性
            this.items = []
            //栈的相关操作
            //1进栈
            Stack.prototype.push = function (el) {
                this.items.push(el)
            }
            //2出栈
            Stack.prototype.pop = function (){
                return this.items.pop()
            }
            //3查看栈顶
            Stack.prototype.peek = function (){
                return this.items[this.items.length - 1]
            }
            //4是否空栈
            Stack.prototype.isEmpty = function (){
                return this.items.length === 0
            }
            //5获取栈元素的个数 
            Stack.prototype.size = function (){
                return this.items.length
            }
            //6正序
            Stack.prototype.order = function (){
                return this.items.join('')
            }
            //7倒序
            Stack.prototype.reverseOrder = function (){
                return this.items.reverse().join('')
            }

        }
        //栈的使用
        let s = new Stack()
        s.push(1)
        s.push(2)
        s.push(3)
        console.log(s.order());



        //十进制转二进制
        function dec2bin(num){
            //1定义一个对象
            let s = new Stack()
            // 
            while(num > 0){
                s.push(num % 2)
                num = Math.floor(num / 2)
            }
            return s.reverseOrder()
        }
        console.log(dec2bin(10));
    </script>
</body>
</html>

二、队列

2.1 基本使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>数组队列</title>
</head>
<body>
    <script>
        function Queue(){
            this.items = []
            //1入队
            Queue.prototype.enQueue = function (el){
                this.items.push(el)
            }
            //2 出队
            Queue.prototype.deQueue = function (){
                return this.items.shift()
            }
            //3 查看第一个元素
            Queue.prototype.front = function(){
                return this.items[0]
            }
            // 4查看是否为空
            Queue.prototype.isEmpty = function (){
                return this.items.length === 0 
            }
            // 5查看个数
            Queue.prototype.size = function (){
                return this.items.length
            }
            //6正序
            Queue.prototype.order = function (){
                return this.items.join('')
            }
        }
        // 实例
        let q = new Queue()
        q.enQueue('a')
        q.enQueue('b')
        q.enQueue('c')
        q.enQueue('d')
        console.log(q.order());

        
    </script>
</body>
</html>

2.2 优先队列

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        function PriorityQueue(){
            function QueueElement(element,priority){
                this.element = element
                this.priority = priority
            }
            this.items = []
            PriorityQueue.prototype.enqueue = function (element,priority){
                // 1创建对象
                let queueElement = new QueueElement(element,priority) 
                // 2判断队列是否为空
                if(this.items.length === 0){
                    this.items.push(queueElement)
                }else {
                    let added = false
                    let n = this.items.length
                    for (let i = 0; i < n; i++) {
                        if(queueElement.priority < this.items[i].priority){
                            this.items.splice(i,0,queueElement)
                            added = true
                            break
                        }
                        //插入到最后
                        if(!added){
                            this.items.push(queueElement)
                        }
                    }
                }
            }
            //2 出队
            PriorityQueue.prototype.deQueue = function (){
                return this.items.shift()
            }
            //3 查看第一个元素
            PriorityQueue.prototype.front = function(){
                return this.items[0]
            }
            // 4查看是否为空
            PriorityQueue.prototype.isEmpty = function (){
                return this.items.length === 0 
            }
            // 5查看个数
            PriorityQueue.prototype.size = function (){
                return this.items.length
            }
            //6正序
            PriorityQueue.prototype.order = function (){
                let str = ''
                for (let i = 0; i < this.items.length-1; i++) {
                    str = str+this.items[i].element+'_'+this.items[i].priority+ ' '
                }
                console.log('我想看一下',this.items);
                return str
            }
        }

        //测试代码
        let pq = new PriorityQueue()
        pq.enqueue('abc',111)
        pq.enqueue('cba',200)
        pq.enqueue('nba',50)
        pq.enqueue('bb',66)
        console.log(pq.order());//nba_50 bb_66 abc_111 cba_200 
    </script>
</body>
</html>

三、链表

3.1 单向链表

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        function LinkedList(){
            function Node(data){
                this.data = data
                this.next = null
            }

            //属性
            this.head = null
            this.length = 0
            //一、追加方法
            LinkedList.prototype.append = function (data) {
                //1如果是第一个节点
                let newNode = new Node(data)
                if(this.length === 0){
                    this.head = newNode
                }else {
                    let current = this.head
                    while(current.next) {
                        current = current.next
                    }
                    current.next = newNode
                }
                //2添加后长度加一
                this.length += 1   
            }

            // 二、tostring方法
            LinkedList.prototype.toString = function (){
                // 1定义变量
                let current = this.head
                let listString = ''

                // 2循环一个个节点
                while(current){
                    listString += current.data + ' '
                    current = current.next
                }
                return listString
            }

            // 三、insert方法
            LinkedList.prototype.insert = function (position,data){
                // 1对position进行越界判断
                if(position < 0 || position > this.length ) return false
                // 2创建对象
                let newNode = new Node(data)
                // 3判断插入的位置是否第一个
                if(position === 0){
                    newNode.next = this.head
                    this.head = newNode
                }else {
                    let i = 0
                    let current = this.head
                    let previous = null
                    while(i++ < position){
                        previous = current
                        current = current.next
                    }
                    newNode.next = current//这个是插入的元素,连接下一个节点
                    previous.next = newNode//这个是插入的元素上一个,连接当前要插入的元素
                }
                // 4长度加一
                this.length += 1
                return true

            }

            // 四、get方法
            LinkedList.prototype.get = function (position) {
                //1越界判断
                if(position < 0 || position >= this.length) return null
                // 2获取对应的元素
                let current = this.head
                let i = 0
                while(i++ < position){
                    current = current.next
                }
                return current.data
            }

            // 五、indexOf方法
            LinkedList.prototype.indexOf = function (data){
                // 1定义变量
                let current = this.head
                let i = 0
                //2 查找
                while(current){
                    if(current.data === data){
                        return i
                    }
                    current = current.next
                    i += 1
                }
                // 3找到最后没有直接返回-1
                return -1
            }
            // 六、update方法
            LinkedList.prototype.update = function (position,data){
                //1越界判断
                if(position < 0 || position >= this.length)return false
                // 2定义变量
                let current = this.head
                let i = 0
                //3 查找
                while(i++ < position){
                    current = current.next
                }
                // 4更新
                current.data = data
                return true
            }
            // 七、removeAt方法,从链表中删除特定一项
            LinkedList.prototype.removeAt = function (position){
                // 1越界判断
                if(position < 0 || position >= this.length)return false
                
                let current = this.head
                // 2当是第0个节点
                if(position === 0){
                    this.head = this.head.next
                }else {
                    let i = 0
                    let previous = null
                    while(i++ < position) {
                        previous = current
                        current = current.next
                    }
                    previous.next = current.next
                }
                //3长度-1
                this.length -= 1
                return true
            }
            // 八、remove方法,从链表中移除一项,根据数据
            LinkedList.prototype.remove = function (data){
                const i = this.indexOf(data)
                return this.removeAt(i)
            }
        }



        //测试代码
        let list = new LinkedList()
        list.append('abc')
        list.append('cba')
        list.append('nba')
        // console.log(list.toString());
        list.insert(0,'aaa')
        list.insert(3,'bbb')
        list.insert(5,'ccc')
        // console.log(list.toString());
        // console.log(list.get(0));
        // console.log(list.get(3));
        // console.log(list.get(5));
        // console.log(list.toString());
        // console.log(list.indexOf('abc'));
        // console.log(list.indexOf('ccc'));
        // console.log(list.indexOf('1231'));
        // console.log(list.toString());
        // console.log(list.update(0,123));
        // console.log(list.update(4,123));
        // console.log(list.toString());
        // console.log(list.removeAt(1))
        // console.log(list.toString());
        // console.log(list.remove('ccc'));
        // console.log(list.toString());


    </script>
</body>
</html>

3.2 双向链表

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 双向链表 -->
    <script>
        function DoublyLinkedList(){
        // 内部类
        function Node(data){
            this.data = data
            this.prev = null//指向前一个指针
            this.next = null//指向后一个指针
        }
        
            // 属性
        this.head = null
        this.tail = null
        this.length = 0

        // 1append方法
        DoublyLinkedList.prototype.append = function (data){
            //  1.1创建节点
            let newNode = new Node(data)
            // 1.2判断是否添加第一个节点
            if(this.length === 0){
                this.head = newNode
                this.tail = newNode
            }else {
                newNode.prev = this.tail
                this.tail.next = newNode
                this.tail = newNode
            }
            // 1.3长度加1
            this.length += 1
        }
        // 2前向遍历,后向遍历
        DoublyLinkedList.prototype.first_back = function(v){
            if(v === 'back'){
                let current = this.head
                let res = ''
                while(current){
                    res += current.data
                    current = current.next
                }
                console.log(res);
            }else {
                let current = this.tail
                let res = ''
                while(current){
                    res += current.data
                    current = current.prev
                }
                console.log(res);
            }
        }
        // 3根据位置插入
        DoublyLinkedList.prototype.insert = function (position, data){
            // 3.1越界判断
            if(position < 0 || position > this.length)return false
            // 3.2创建新节点
            let newNode = new Node(data)
            // 3.3判断原来列表是否为空
            if(this.length === 0 ){
                this.head = newNode
                this.tail = newNode
            }else {
                // 3.31假如插入的位置是0
                if(position === 0){
                    this.head.prev = newNode
                    newNode.next = this.head
                    this.head = newNode
                    // 假如插入的最后一个位置
                }else if(position === this.length){
                    newNode.prev = this.tail
                    this.tail.next = newNode
                    this.tail = newNode
                }else {
                    let current = this.head
                    let i = 0
                    while(i++ < position){
                        current = current.next
                    }
                    newNode.next = current
                    newNode.prev = current.prev
                    current.prev.next = newNode
                    current.prev = newNode
                    
                }
            }
            // 4长度加一
            this.length += 1
            return true
        }
        // 4get方法
        DoublyLinkedList.prototype.get = function (position){
            // 4.1越界判断
            if(position < 0 || position > this.length)return null
            // 4.2获取元素
            let current = this.head
            let i = 0
            while(i++ < position){
                current = current.next
            }
            console.log('查找到的值--------',current.data);
            return current.data

        }
        
    }

    // 测试代码

    let list = new DoublyLinkedList()
    list.append('aaa')
    list.append('ccc')
    list.append('zzz')
    // list.first_back('back')//从前往后
    // list.first_back()//从后往前
    // list.insert(3,'000')
    // list.first_back('back')//从前往后
    // list.get(0)
    </script>
</body>
</html>

四、哈希表

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>哈希表</title>
</head>

<body>
    <script>
        // 这个是哈希表
        function HashTable() {
            // 属性
            this.storage = []
            this.count = 0//记录当前已存放的个数
            this.limit = 7//总长度
            // 方法
            // 这个是哈希函数
            HashTable.prototype.hashFunc = function (str, size) {
                // 1定义hashCode变量
                let hashCode = 0
                // 2计算值
                // Unicode码
                for (let i = 0; i < str.length; i++) {
                    hashCode = 37 * hashCode + str.charCodeAt(i)
                }
                // 3取余
                let index = hashCode % size
                return index
            }
            // 插入/修改
            HashTable.prototype.put = function (key, value) {
                // 1根据key获取对应的index
                let index = this.hashFunc(key, this.limit)
                // 2根据index获取对应的bucket
                let bucket = this.storage[index]
                // 3判断bucket是否为空,如果为空创建一下
                if (bucket == null) {
                    this.storage[index] = []
                }
                // 4判断是否修改数据
                for (let i = 0; i < bucket.length; i++) {
                    let tuple = bucket[i]
                    if (tuple[0] === key) {
                        tuple[1] = value
                        return
                    }
                }
                // 5如果不是修改,直接添加
                bucket.push([key, value])
                this.count += 1

                // 6扩容
                if (this.count > this.limit * 0.75) {
                    let newPrime = this.getPrime(this.limit * 2)
                    this.resize(newPrime)
                }
            }
            // 查找
            HashTable.prototype.get = function (key) {
                // 1根据key获取index
                let index = this.hashFunc(key, this.limit)
                // 2根据index获取对应的bucket
                let bucket = this.storage[index]
                // 3判断是否为空,是的话直接返回
                if (bucket == null) return null
                // 4有bucket的话,线性查找
                for (let i = 0; i < bucket.length; i++) {
                    let tuple = bucket[i]
                    if (tuple[0] === key) {
                        return tuple[1]
                    }
                }
                // 5如果没有找到
                return null
            }
            // 删除
            HashTable.prototype.remove = function (key) {
                // 1根据key获取index
                let index = this.hashFunc(key, this.limit)
                // 2根据index获取对应的bucket
                let bucket = this.storage[index]
                // 3判断是否为空,是的话直接返回
                if (bucket == null) return null
                // 4有bucket的话,线性查找,并且删除
                for (let i = 0; i < bucket.length; i++) {
                    let tuple = bucket[i]
                    if (tuple[0] === key) {
                        bucket.splice(i, 1)
                        this.count--
                        // 缩小容量,最小容量为7
                        if (this.limit > 7 && this.count < this.limit * 0.25) {
                            let newPrime = this.getPrime(Math.floor(this.limit / 2))
                            this.resize(newPrime)
                        }
                        return tuple[1]
                    }
                }
                // 5如果没有找到
                return null
            }
            //哈希表是否为空
            HashTable.prototype.isEmpty = function () {
                return this.count === 0
            }
            //获取元素个税,所有
            HashTable.prototype.size = function () {
                return this.count
            }
            // 扩容
            HashTable.prototype.resize = function (newLimit) {
                // 1保存旧数组的内容
                let oldStroage = this.storage
                // 2重置所有属性
                this.storage = []
                this.count = 0
                this.limit = newLimit
                // 3循环oldStroage所有的bucket
                for (let i = 0; i < oldStroage.length; i++) {
                    // 3.1取出桶
                    let bucket = oldStroage[i]
                    // 3.2判断桶是否为空,为空直接下一次循环
                    if (bucket == null) continue
                    // 3.3bucket中有数据取出数据,重新插入
                    for (let j = 0; j < bucket.length; j++) {
                        let tuple = bucket[j]
                        this.put(tuple[0], tuple[1])
                    }
                }
            }
            // 判断是不是质数
            HashTable.prototype.isPrime = function (num) {
                // 1获取num的平方根
                let temp = parseInt(Math.sqrt(num))
                for (let i = 2; i <= temp; i++) {
                    if (num % 2 === 0) {
                        return false
                    }
                }
                return true
            }
            // 获取质数的方法
            HashTable.prototype.getPrime = function (num) {
                while (!this.isPrime(num)) {
                    num++
                }
                return num
            }
        }
        // 测试代码
        let ht = new HashTable()
        ht.put('aaa', '111')
        ht.put('bbb', '222')
        ht.put('ccc', '333')
    </script>
</body>

</html>

五、合集

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>集合</title>
</head>

<body>
    <script>
        function Set() {
            // 属性
            this.items = {}
            // 方法
            Set.prototype.add = function (value) {
                // 如果已有属性,就退出
                if (this.has(value)) return false
                this.items[value] = value
                return true
            }
            // has方法,是否有这个属性
            Set.prototype.has = function (value) {
                return this.items.hasOwnProperty(value)
            }
            // remove
            Set.prototype.remove = function (value) {
                // 1是否包含
                if (!this.has(value)) return false
                // 2如果有,就删除
                delete this.items[value]
                return true
            }
            // clear方法
            Set.prototype.clear = function () {
                this.items = {}
            }
            // size方法
            Set.prototype.size = function () {
                return Object.keys(this.items).length
            }
            // 属性数组
            Set.prototype.values = function () {
                return Object.keys(this.items)
            }
            // 并集
            Set.prototype.union = function (otherSet) {
                let unionSet = new Set()
                let values = this.values()
                // 把当前的加进去
                for (let i = 0; i < values.length; i++) {
                    unionSet.add(values[i])
                }
                // 把传进来的加进去
                values = otherSet.values()
                for (let i = 0; i < values.length; i++) {
                    unionSet.add(otherSet[i])
                }

                return unionSet

            }
            // 交集
            Set.prototype.intersection = function (otherSet) {
                let intersection = new Set()
                let values = this.values()
                for (let i = 0; i < values.length; i++) {
                    if (otherSet.has(values[i])) {
                        intersection.add(values[i])
                    }
                }
                return intersection
            }
            // 差集
            Set.prototype.difference = function (otherSet) {
                let differenceSet = new Set()

                let values = this.values()
                for (let i = 0; i < values.length; i++) {
                    if (!otherSet.has(values[i])) {
                        differenceSet.add(values[i])
                    }
                }
            }
            // 子集
            Set.prototype.subset = function (otherSet) {
                let values = this.values()
                for (let i = 0; i < values.length; i++) {
                    if (!otherSet.has(values[i])) return false
                }
                return true
            }
        }
        // 测试代码
        // 交集
        let set_1 = new Set()
        set_1.add('aaa')
        set_1.add('bbb')
        set_1.add('ccc')
        let set_2 = new Set()
        set_2.add('bbb')
        // console.log(set_1.intersection(set_2));
        // 子集
        console.log(set_2.subset(set_1));
    </script>
</body>

</html>

六、二叉树

6.1 二叉搜索树

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>二叉搜索树</title>
</head>

<body>

    <script>
        function BinarySerachTree() {
            function Node(key) {
                this.key = key
                this.left = null
                this.right = null
            }
            // 属性
            this.root = null
            // 一、插入
            BinarySerachTree.prototype.insert = function (key) {
                // 1根据key创建节点
                let newNode = new Node(key)
                // 2判断跟节点是否有值
                if (this.root == null) {
                    this.root = newNode
                } else {
                    this.insertNode(this.root, newNode)
                }
            }
            // 递归调用
            BinarySerachTree.prototype.insertNode = function (node, newNode) {
                if (newNode.key < node.key) {
                    // 左叶子
                    if (node.left == null) {
                        node.left = newNode
                    } else {
                        this.insertNode(node.left, newNode)
                    }
                } else {
                    // 右叶子
                    if (node.right == null) {
                        node.right = newNode
                    } else {
                        this.insertNode(node.right, newNode)
                    }
                }
            }
            // 二、先序遍历
            BinarySerachTree.prototype.preOrderTraversal = function (handler) {
                this.preOrderTraversalNode(this.root, handler)
            }
            BinarySerachTree.prototype.preOrderTraversalNode = function (node, handler) {
                if (node != null) {
                    // 1处理经过的节点
                    handler(node.key)
                    // 2处理经过的左节点
                    this.preOrderTraversalNode(node.left, handler)
                    // 3处理经过的右节点
                    this.preOrderTraversalNode(node.right, handler)
                }
            }
            // 三,中序遍历
            BinarySerachTree.prototype.midOrderTraversal = function (handler) {
                this.midOrderTraversalNode(this.root, handler)
            }
            BinarySerachTree.prototype.midOrderTraversalNode = function (node, handler) {
                if (node != null) {
                    // 1处理左
                    this.midOrderTraversalNode(node.left, handler)
                    // 2处理节点
                    handler(node.key)
                    // 3处理右
                    this.midOrderTraversalNode(node.right, handler)
                }
            }
            // 四、后序遍历
            BinarySerachTree.prototype.postOrderTraversal = function (handler) {
                this.postOrderTraversalNode(this.root, handler)
            }
            BinarySerachTree.prototype.postOrderTraversalNode = function (node, handler) {
                if (node != null) {
                    // 1处理左
                    this.postOrderTraversalNode(node.left, handler)
                    // 2处理右
                    this.postOrderTraversalNode(node.right, handler)
                    // 3处理节点
                    handler(node.key)
                }
            }
        }

        // 测试代码
        const bst = new BinarySerachTree()
        bst.insert(2)
        bst.insert(1)
        bst.insert(3)
        // 先序,根左右
        let left = ''
        bst.preOrderTraversal(function (key) {
            left += key + ' '
        })
        console.log('先序,根左右', left);
        // 中序,左根右
        let center = ''
        bst.midOrderTraversal(function (key) {
            center += key + ' '
        })
        console.log('中序,左根右', center);
        // 后序,左右根
        let right = ''
        bst.midOrderTraversal(function (key) {
            right += key + ' '
        })
        console.log('后序,左右根', right);
    </script>
</body>

</html>

待续呀...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值