JavaScript全解析-设计模式

news/2024/6/3 21:28:13 标签: 设计模式, 单例模式

●为了解决一类问题给出的 简洁而优化 的解决方案
设计模式不是规则,是程序员开发过程中的经验总结

单例模式
●一个构造函数一生只有一个 实例对象

<script>
    function Person(name) {
        this.name = name
    }
    // 核心代码
    let instance = null
    function singleton() {
        if (!instance) instance = new Person('Jack')
        return instance
    }
    // 实现单例模式创建实例对象
    // 第一次调用 singleton() 函数, 此时 instance 就是 null
    // if 条件为 true, 给 instance 赋值
    // 赋值为一个 Person 的实例
    // return instance, 把 instance 保存的值赋值给了 p1
    // p1 拿到的是 Person 的实例
    const p1 = singleton()
    // 第二次调用 singleton() 函数, 此时 instance 是Perosn 的实例
    // if 条件为 false, 后面的代码不执行
    // 直接执行 return instance
    // 又一次把 Person 的实例返回了
    // 赋值给了 p2 变量
    // p2 拿到的还是 Person 之前的哪一个实例
    const p2 = singleton()
    console.log(p1, p2)
    console.log(p1 === p2)
</script>


复制代码

单例模式变形
●利用闭包和自执行函数结合的方式实现

function Person(name) {
    this.name = name
}
let instance = null
function singleton() {
    if (!instance) instance = new Person('Jack')
    return instance
}
// 我们要以闭包的形式得到singleton 不让都暴露在全局
// 这里我们要使用的就是自执行函数
const singleton = (function outer() {
    function Person(name) {
        this.name = name
    }
    let instance = null
    return function inner() {
        if (!instance) instance = new Person('Jack')
        return instance
    }
})()
// const p1 = singleton()
// const p2 = singleton()
// console.log(p1, p2);
// console.log(p1 === p2);
// 到了这里我们该放进去的都放进去了接下来我们继续变形
/* 
    Person这个变量名现在只在函数里面有作用
    如果我现在把singleton变成Person 和里面的Person有没有影响?
    是没有影响的
    我们先不改变 为了好说
    现在要弄明白一个问题 就是外面的singleton()调用的是那个函数
*/
const singleton = (function outer() {
    function Person(name) {
        this.name = name
    }
    // 在Person的原型对象上定义一个方法 用来修改Person构造函数里面的name的值
    Person.prototype.setName = function (val) { this.name = val }
    // 单例的核心代码
    let instance = null
    return function inner(name) {
        if (!instance) instance = new Person()
        // 这里调用setName函数
        instance.setName(name)
        // 这个位置的instance就是person的实例
        return instance
    }
})()
// const p1 = singleton('Rose')
console.log(p1);
// const p2 = singleton('Jack')
console.log(p2);
console.log(p1 === p2);
// 再次修改变量
const Person = (function outer() {
    function Person(name) {
        this.name = name
    }
    // 在Person的原型对象上定义一个方法 用来修改Person构造函数里面的name的值
    Person.prototype.setName = function (val) { this.name = val }
    // 单例的核心代码
    let instance = null
    return function inner(name) {
        if (!instance) instance = new Person()
        // 这里调用setName函数
        instance.setName(name)
        // 这个位置的instance就是person的实例
        return instance
    }
})()
// 所以这个时候我们写new也没有关系
// 因为return的是一个复杂数据类型 自动创建的能力没有了 
const p1 = new Person('Rose')
console.log(p1);
const p2 = new Person('Jack')
console.log(p2);
console.log(p1 === p2);


复制代码

案例-自定义弹出层
结构

   <!-- 整个弹出层 -->
    <div class="dialog">
        <!-- 顶部内容 -->
        <div class="top">
            <p>提示</p>
            <span>X</span>
        </div>
        <!-- 中间内容区域 -->
        <div class="content">
            真实内容
        </div>
        <!-- 底部区域 -->
        <div class="bottom">
            <button>确定</button>
        </div>
    </div>


复制代码

样式


.dialog {
            width: 600px;
            height: 360px;
            border-top: 1px solid #ccc;
            border-left: 1px solid #ccc;
            box-shadow: 1px 2px 2px 0px #ccc;
            background-color: #fff;
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            margin: auto;
            display: flex;
            flex-direction: column;
            border-radius: 15px;
        }
        .dialog > .top {
            height: 45px;
            background-color: skyblue;
            display: flex;
            box-sizing: border-box;
            justify-content: space-between;
            padding: 0 20px;
            align-items: center;
            border-bottom: 1px solid #ccc;
            border-radius: 15px 15px 0 0;
        }
        .dialog > .top > p {
            font-size: 22px;
            font-weight: 700;
            color: #fff;
        }
        .dialog > .top > span {
            cursor: pointer;
        }
        .dialog > .bottom {
            height: 45px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-top: 1px solid #ccc;
        }
        .dialog > .bottom > button {
            font-size: 20px;
            padding: 0 10px;
            cursor: pointer;
        }
        .dialog > .content {
            flex: 1;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 20px;
        }


复制代码

交互

// 书写单例模式代码
const Dialog = (function () {

    // 构造函数体
    class Dialog {
        constructor () {
            this.dialog = document.createElement('div')
            // 顶部面板
            this.top = null
            // 面板内的文本
            this.desc = null
            // 中间的内容区域
            this.content = null
            // 底部
            this.bottom = null
  
  
            // 面本内的文本
            this.descText = '提示'
            // 提示文本内容
            this.title = '你好 世界'
            // 颜色和文本你对照表
            this.list = [
            {
                name: 'success',
                descText: '成功',
                bgColor: 'green'
            },
            {
                name: 'danger',
                descText: '危险',
                bgColor: 'red'
            },
            {
                name: 'warning',
                descText: '警告',
                bgColor: 'orange'
            },
            {
                name: 'default',
                descText: '提示',
                bgColor: '#fff'
            },
            {
                name: 'info',
                descText: '信息',
                bgColor: 'skyblue'
            }
            ]
    
            this.single()
        }
    
        // 只执行一次
        single () {
            this.creHTML()
            this.setCss()
            this.bindEvent()
        }
  
        // 创建整体结构
        creHTML () {
            // 创建 top 结构
            this.top = document.createElement('div')
            this.desc = document.createElement('p')
            this.desc.innerText = this.descText
            this.span = document.createElement('span')
            this.span.innerText = 'X'
            // 把 p 和 span 插入到 top 内
            this.top.appendChild(this.desc)
            this.top.appendChild(this.span)
  
  
            // 创建内容结构
            this.content = document.createElement('div')
            this.content.innerText = this.title
    
            // 创建底部结构
            this.bottom = document.createElement('div')
            this.btn = document.createElement('button')
            this.btn.innerText = '确定'
            this.bottom.appendChild(this.btn)
  
            // 把创建好的结构插入到 dialog 内
            this.dialog.appendChild(this.top)
            this.dialog.appendChild(this.content)
            this.dialog.appendChild(this.bottom)
    
            // 把创建好的 dialog 结构插入到 页面内
            document.body.appendChild(this.dialog)
        }
  
        // 设置 css 样式
        setCss () {
            // 给 dialog 设置样式
            setStyles(this.dialog, {
                width: '600px',
                height: '360px',
                'border-top': '1px solid #ccc',
                'border-left': '1px solid #ccc',
                'box-shadow': '1px 2px 2px 0px #ccc',
                'background-color': '#fff',
                position: 'fixed',
                top: 0,
                left: 0,
                right: 0,
                bottom: 0,
                margin: 'auto',
                display: 'flex',
                'flex-direction': 'column',
                'border-radius': '15px',
            })
  
            // 给 top 设置样式
            setStyles(this.top, {
                height: '45px',
                'background-color': 'skyblue',
                display: 'flex',
                'box-sizing': 'border-box',
                'justify-content': 'space-between',
                padding: '0 20px',
                'align-items': 'center',
                'border-bottom': '1px solid #ccc',
                'border-radius': '15px 15px 0 0'
            })
  
            // 给 content 设置样式
            setStyles(this.content, {
                flex: 1,
                display: 'flex',
                'justify-content': 'center',
                'align-items': 'center',
                'font-size': '20px'
            })
  
            // 给 bottom 设置样式
            setStyles(this.bottom, {
                height: '45px',
                display: 'flex',
                'align-items': 'center',
                'justify-content': 'center',
                'border-top': '1px solid #ccc'
            })
  
            // 给 面板提示 设置样式
            setStyles(this.desc, {
                'font-size': '22px',
                'font-weight': 700
            })
  
            // 给 面板的 关闭按钮
            setStyles(this.span, {
                cursor: 'pointer'
            })
  
            // 底部按钮
            setStyles(this.btn, {
                'font-size': '20px',
                padding: '0 10px',
                cursor: 'pointer'
            })
        }
  
        // 事件绑定
        bindEvent () {
            this.btn.addEventListener('click', () => {
                this.dialog.style.display = 'none'
            })
            this.span.addEventListener('click', () => {
               this.dialog.style.display = 'none'
            })
        }
  
        // 每次都要执行
        init (title = '', type = 'default') {
            // 根据你的 文本 和 关键字 设置内容
            // 1. 根据类型获取到对照表内的对应信息
            const info = this.list.find(item => item.name === type) || { name: 'default', descText: '提示', bgColor: '#fff' }
            // 2. 根据 info 的内容开始设置
            this.top.style.backgroundColor = info.bgColor
            this.desc.innerText = info.descText
            this.descText = info.descText
            this.content.innerText = title
            this.title = title
  
            // 让 dialog 显示出来
            this.dialog.style.display = 'flex'
        }
    }
  
    // 功能函数
    function setStyles(ele, styles) {
        for (let k in styles) {
            ele.style[k] = styles[k]
        }
    }
  
    // 单例模式核心代码
    let instance = null
    return function (...arg) {
        if (!instance) instance = new Dialog()
        instance.init(...arg)
        return instance
    }
  })()


复制代码

发布订阅模式


<!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>
        /* 
            发布订阅模式
            例子: 去书店买书
            没有设计模式 就是面向过程
                => 去到书店 , 问有没有书 , 没有就回去了,
                => 过一会儿 , 在去书店问问有没有书 , 没有就回去
                => 过一会儿 , 在去书店问问有没有书 , 没有就回去
                => 过一会儿 , 在去书店问问有没有书 , 没有就回去
                => 过一会儿 , 在去书店问问有没有书 , 没有就回去
                => 过一会儿 , 在去书店问问有没有书 , 没有就回去
                => 过一会儿 , 在去书店问问有没有书 , 没有就回去
                => .....
                => 过一会儿 , 去到书店问问有没有书 , 有了 , 买回去
            发布订阅模式
                => 去到书店 , 问有没有书 , 没有的话留下一个电话号码 , 有了给我打电话
                => 回去等待电话
                => 接到电话了去到书店把书买回去

            发布订阅: 把你想要做的事情都写好(也就是注册到on函数中) , 将来一触发(就是执行了trigger函数)就都做完了
        */

        // 代码实现
        class Observer{
            constructor(status){
                // 表示你的初始状态 , 将来一旦这个状态发生了改变我们要触发
                // 也就是一旦有书了要通知人来买
                this.status = status

                // 定义个消息盒子 , 记录的都有谁和我定了书
                // 定了几本书 , 都有那些书 , 是不是要记录上啊
                this.message = {}
            }

            // 在原型上定义几个方法
            // 这个表示注册一个事件
            // 下面函数调用了传递了实参 , 我们这里要接受形参
            on (type,fn) {
                // type 事件类型
                // fn   事件处理函数
                // 接下来我们要绑定在message内部
                // 我们要判断message内部有没有type这个类型
                // 如果没有我们就让它称为一个数组
                if(!this.message[type]) this.message[type] = []
                // 之后我们向向消息盒子内添加函数
                this.message[type].push(fn)
            }

            // 这个表示取消这个事件
            // 也要接收两个参数
            off (type , fn) {
                // 这个时候我们也要先判断消息盒子中有没有这个类型
                // 如果没有 , 我们就什么都不用做了
                if(!this.message[type]) return
                // 代码能执行到这里说名有这个函数
                // 那我们就解绑这个函数就好了
                // 如何解绑呢?
                this.message[type] = this.message[type].filter(item => item !== fn) // 把不一样的重新赋值 , 那就把一样的筛出去了
            }

            // 触发事件
            trigger (type) {
                // 首先要判断有没有这个事件 , 如果没有就什么都不做了
                if(!this.message[type]) return
                // 代码能执行到这里说明有这个事件
                // 那接下来就触发这个事件就好了
                // 里面就是每一个函数 , 直接调用就可以了
                this.message[type].forEach(item => item())
            }
        }

        // 实例化个对象
        // 这就是一个第三方 , 你可以把这个当做是书店的店员
        const o = new Observer('没有')
        // console.log(o);

        // 准备几个函数
        function handlerA() { console.log('handlerA');}
        function handlerB() { console.log('handlerB');}
        function handlerC() { console.log('handlerC');}

        // 向o 上注册一个事件
        // js这本书来了 , 执行handlerA这个函数
        o.on('js',handlerA)
        o.on('js',handlerB)
        o.on('css',handlerA)
        o.on('css',handlerC)
        o.on('html',handlerB)
        o.on('html',handlerC)
        console.log(o);

        // 向 o 取消一个事件注册
        // 也就是我从别的地方买到这本书了 , 不要在给我打电话了
        o.off('js',handlerA)

        // 都注册好了以后由店员来触发这个事件
        o.trigger('js') // 表示js这本书来了 , 这样就触发了这个函数
        
    </script>
</body>
</html>


复制代码

策略模式
●也是设计模式的一种 , 也是相对来说用的比较多的一种
●作用:
○减少if条件的判断
○就是把多种形式的内容罗列出来
●核心
○就是用一个数据结构 , 把各种操作记录下来
○值存储的就是操作后的结果
●例子
○需求:
=> 我已知一个购物总价 1356
=> 需要根据折扣计算最终价格
=> 折扣种类 8折 7折 300-20 500-50
实现:
=> 我们需要在标签上记录一个属性
=> 能记录到我们的各种折扣
=> 如果折扣有很多呢? 如果后期需要添加或者减少折扣呢?
=> 这样操作就能麻烦
●之前的实现方式


const type = '80%' // '70%' '300-20' '500-50'
if (type === '80%') {
} else if (type === '70%') {
    console.log('逻辑实现');
} else if (type === '300-20') {
    console.log('逻辑实现');
} else if (type === '500-50') {
    console.log('逻辑实现');
} else if (type === '300-30') {
    console.log('逻辑实现');
}


复制代码

策略模式


// 我们利用的还是闭包
const discount = (function () {
    // 留存一份数据结构
    const discountList = {
        // 这里的数据要如何设计
        // 需要有折扣类型和折扣以后的价格
        // 标识:能计算出最后的价格(这里的将来需要调用实现 , 也就是这里需要一个函数)
        '80%':function (total) { return (total * 0.8).toFixed(2) }
    }
    // 因为要使用闭包 , 我们需要返回一个函数
    function inner(total,type) {
        // 这里我们出计算方式
        // 这里需要根据传递进来的折扣查看discountList中有没有这个折扣就好了
        // 需要把 type 当做键来访问 discountList
        // 如果有返回的是一个函数 , 如果没有返回的是一个undefined
        // console.log(discountList[type]);
        // 判断有没有这个折扣 , 没有这个折扣就返回总价
        if (!discountList[type]) return total 
        // 代码能执行到这里说明是有这个折扣的
       return discountList[type](total) - 0
    }
    // 这里把inner函数当做一个对象来看待 , 向里面插入一些方法
    // 添加一个方法 , 专门用来向 discountList内添加折扣类型
    inner.add = function (type,fn) {
        // type:表示添加的折扣
        // fn: 是一个函数,用来计算出最后的价格
        // console.log(type);
        // console.log(fn);
        // 添加到 discountList中
        discountList[type] = fn
    }
    // 添加一个方法 , 用来删除一种折扣
    inner.remove = function (type) {
        // 删除掉这个折扣
        delete discountList[type]
    }
    // 我们含可以把这个折扣的列表返回出去查看
    inner.getList = function () {
        return discountList
    }
    // 这里返回inner函数
    return inner
})()
// 将来使用
// const res = discount('总价','折扣类型')
const res = discount(1000,'80%')
console.log(res);
// 将来使用添加的折扣
discount.add('300-20', price => price - parseInt(price / 300) * 20)
// 添加完毕以后需要在下面计算
const res1 = discount(1000,'300-20')
console.log(res1);
// 查看折扣列表
const list = discount.getList()
console.log(list);


复制代码

案例-收银台


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    body {
      padding-left: 200px;
    }

    input, button {
      outline: none;
    }

    ul, li {
      list-style: none;
    }

    .addSale, .calc {
      width: 200px;
      height: 33px;
      background-color: skyblue;
      color: #fff;
      cursor: pointer;
      border: none;
      margin: 30px;
    }

    input {
      width: 300px;
      height: 30px;
      padding-left: 20px;
      font-size: 22px;
      display: block;
      margin: 20px;
    }

    ul {
      display: flex;
      margin: 20px;
    }

    ul > li {
      width: 120px;
      height: 120px;
      background-color: orange;
      margin: 10px;
      display: flex;
      justify-content: center;
      align-items: center;
      color: #fff;
      font-size: 30px;
      cursor: pointer;
    }

    ul > li.active {
      background-color: skyblue;
    }

    p {
      font-size: 100px;
      color: red;
      margin: 20px;
    }

  </style>
</head>
<body>

  <button class="addSale">添加折扣类型</button>

  <!-- 总价格 -->
  <input type="text">

  <!-- 折扣类型 -->
  <ul>
    <li class="active">1111</li>
    <li>1111</li>
    <li>1111</li>
  </ul>

  <button class="calc">计算总价</button>

  <!-- 最终价格 -->
  <p>0.00</p>


  折扣名称(显示在按钮上的文本): <input type="text" class="type">
  计算方式(总价以 x 表示): <input type="text" class="method">

  <script>
    /*
      收银台
    */

    // 0. 获取元素
    const ulBox = document.querySelector('ul')
    const calcBtn = document.querySelector('.calc')
    const totalInp = document.querySelector('input')
    const pBox = document.querySelector('p')

    const addBtn = document.querySelector('.addSale')
    const nameInp = document.querySelector('.type')
    const methodInp = document.querySelector('.method')

    // 0. 以策略模式的形式准备一个 折扣记录
    const calcPrice = (function () {

      // 折扣列表
      const calcList = {
        '80%': function (total) { return (total * 0.8).toFixed(2) },
        '70%': function (total) { return (total * 0.7).toFixed(2) }
      }

      function inner(total, type) {
        if (!calcList[type]) return '0.00'

        return calcList[type](total)
      }

      inner.add = function (type, fn) {
        calcList[type] = fn
      }

      inner.remove = function (type) {
        delete calcList[type]
      }

      inner.getList = function () {
        return calcList
      }

      return inner
    })()

    // 0. 准备变量
    let type = ''

    // 1. 拿到当前所有的折扣渲染 li
    // 将来一旦折扣添加了, 需要重新渲染 li
    bindHtml()
    function bindHtml() {
      // 1-1. 拿到折扣类型列表
      const list = calcPrice.getList()

      // 1-2. 利用 list 渲染 li
      let str = ''
      for (let k in list) {
        str += `
          <li data-type="${ k }">${ k }</li>
        `
      }

      ulBox.innerHTML = str
    }


    // 2. 折扣类型的选择(排他)
    tab()
    function tab() {
      ulBox.addEventListener('click', e => {
        if (e.target.nodeName !== 'LI') return

        // 所有的没有类名
        for (let i = 0; i < ulBox.children.length; i++) {
          ulBox.children[i].classList.remove('active')
        }

        // 当前这个有类名
        e.target.classList.add('active')

        // 记录下当前的折扣类型
        type = e.target.dataset.type
      })
    }

    // 3. 结算按钮的事件
    calcBtn.addEventListener('click', () => {
      // 3-1. 拿到总价
      const totalPrice = totalInp.value - 0

      // 3-2. 计算最终价格
      const resultPrice = calcPrice(totalPrice, type)

      // 3-3. 把最终价渲染
      pBox.innerText = resultPrice
    })

    // 4. 添加折扣
    // 我们只能期望用户给我们两个内容
    //   折扣名称
    //   计算方式
    addBtn.addEventListener('click', () => {

      // 4-1. 拿到折扣名称
      const name = nameInp.value

      // 4-2. 拿到公式
      // 开始组装
      const r = '(parseInt(' + methodInp.value + ')).toFixed(2)'

      // 语法: eval(字符串)
      // 作用: 把该字符串当做js代码来执行
      // const res = eval(r)

      // 开始添加了
      calcPrice.add(name, x => eval(r))

      // 4-3. 从新渲染一遍 li
      bindHtml()

      // 4-4. 把两个文本框清空
      nameInp.value = ''
      methodInp.value = ''
    })
  </script>
</body>
</html>



复制代码

模块模式
●要是设计模式中的一种
● 模块模式可以指定类想暴露的属性和方法,并且不会污染全局。采用闭包的形式

 // 定义个自执行函数
var Person = (function() {
    // 定义一个变量
    var name = 'rose'
    // 定义一个函数(方法)
    function sayName() {
        console.log('我的名字是:',name)
    }
    // 返回一个对象
    // 因为是自执行函数 , Person得到的就是一个对象
    // return {
    //     name: name,
    //     sayName: sayName
    // }
    return {
        name,
        sayName
    }
})()
// 使用
console.log(Person);
Person.sayName()

http://www.niftyadmin.cn/n/323602.html

相关文章

Linux实操篇---常用的基本命令1(跟文件操作相关的命令)

一、常用的基本命令 1.常用的shell命令 Shell可以看作是一个命令解释器&#xff0c;为我们提供了交互式的文本控制台界面。 目前的发行版本&#xff1a;在bin/sh 最早的版本Unix&#xff1a;Bourne shell—>Bourne Again Shell 取了 B A Sh。因此目前Linux的发行版大多数…

初识Java多线程编程

文章目录 一、线程的状态二、线程的常见属性三、多线程编程Thread类常用构造方法1.继承Thread类2.实现Runnable接口3.匿名内部类实现4.lambda 表达式创建 Runnable 子类对象 四、线程的常见方法 一、线程的状态 //线程的状态是一个枚举类型 Thread.State public class ThreadS…

Prompt工程师指南[应用篇]:Prompt应用、ChatGPT|Midjouney Prompt Engineering

Prompt工程师指南[应用篇]&#xff1a;Prompt应用、ChatGPT|Midjouney Prompt Engineering 1.ChatGPT Prompt Engineering 主题&#xff1a; 与 ChatGPT 对话 Python 笔记本 Topics: ChatGPT介绍审查对话任务与ChatGPT对话Python笔记本 ChatGPT介绍 ChatGPT是OpenAI训练的…

做网络爬虫需要掌握哪些技术?

网络爬虫是指通过代码自动化地访问网页并收集数据的程序&#xff0c;要开发一个成功的爬虫&#xff0c;需要掌握以下技术&#xff1a; 1. HTTP 协议&#xff1a;了解 HTTP 请求和响应的基本内容&#xff0c;以及如何使用 HTTP 请求头和响应头来优化爬虫性能。 2. HTML/CSS/Ja…

【FATE联邦学习】高度costumized定制联邦学习 costumize all所有步骤

overview https://fate.readthedocs.io/en/latest/zh/tutorial/pipeline/nn_tutorial/ 使用自己的数据集 homo场景&#xff1a; https://fate.readthedocs.io/en/latest/tutorial/pipeline/nn_tutorial/Homo-NN-Customize-your-Dataset/ hetero场景&#xff1a;https://fate…

哈希(hash)

文章目录 一. 哈希思想二. 哈希冲突三. 哈希函数(1). 直接定址法--(常用)(2). 除留余数法--(常用)(3). 平方取中法--(了解)(4). 折叠法--(了解)(5). 随机数法--(了解)(6). 数学分析法--(了解) 结束语 一. 哈希思想 在顺序结构以及树结构中&#xff0c;元素关键码和其存储位置没…

代码随想录算法训练营第十六天|104.二叉树的最大深度 559.n叉树的最大深度 111.二叉树的最小深度 222.完全二叉树的节点个数

文章目录 104.二叉树的最大深度 559.n叉树的最大深度思路代码总结 111.二叉树的最小深度思路代码总结 222.完全二叉树的节点个数思路代码总结 104.二叉树的最大深度 559.n叉树的最大深度 思路 本题可以使用前序&#xff08;中左右&#xff09;&#xff0c;也可以使用后序遍历…

MySQL高级查询操作

文章目录 前言聚集函数分组查询&#xff1a;GROUP BY过滤&#xff1a;HAVING嵌套子查询比较运算中使用子查询带有IN的子查询SOME(子查询)ALL(子查询)EXISTS子查询 前言 查询语句书写顺序&#xff1a; 1、select 2、from 3、where 4、group by 5、having 6、order by 7、limit …