JS数据结构与算法(排序算法的实现)

// 封装一个列表类 
function arrayList() {
    this.array = []

    // 追加方法
    this.append = function (item) {
        this.array.push(item)
    }

    //将数组转化为字符串
    this.toString = function () {
        return this.array.join('-')
    }

    // 实现排序算法

    // 封装交换位置函数
    this.swap = function (m, n) {
        let temp = this.array[m]
        this.array[m] = this.array[n]
        this.array[n] = temp
    }

    // 冒泡排序  比较次数和交换次数都是O(n²)
    this.bubbleSort = function () {
        let length = this.array.length
        //通过嵌套两次循环,每次循环排除一个元素(length-1) 
        for (let i = length - 1; i >= 0; i--) {
            // 两两比较、交换,大的往后靠,循环完毕最后一个位置必是最大值
            for (let j = 0; j < i; j++) {
                if (this.array[j] > this.array[j + 1])
                    this.swap(j, j + 1)
            }
        }
    }

    // 选择排序 比较次数是O(n²),交换次数是O(N)
    this.selectionSort = function () {
        let length = this.array.length
        // 1、先循环数组 拿下标0跟其他所有数比较,如果更小则交换到下标0来
        for (let j = 0; j < length; j++) {
            let min = j //记录下标
            for (let i = j + 1; i < length; i++) {
                if (this.array[min] > this.array[i]) {
                    // 经过不断的循环赋值,此时j就是最小值
                    min = i
                }
            }
            this.swap(j, min)
        }
    }

    // 插入排序 比较次数是O(n²),复制次数是O(N) 但是真实次数实际上是更少的
    this.insertSort = function () {
        let length = this.array.length
        // 外层循环
        for (let i = 1; i < length; i++) {
            let temp = this.array[i]
            let j = i
            while (this.array[j - 1] > temp && j > 0) { //比如 9 5  4 前面更大就位移 把 5 给 4
                this.array[j] = this.array[j - 1]
                j--
            }
            // 此时的J一定是0
            this.array[j] = temp //进行复原4 9 5 不复原的话是9 9 5
        }
    }

    // 希尔排序
    this.shellSort = function () {
        let length = this.array.length
        // 初始化间隔
        let gap = Math.floor(length / 2)

        // 外层循环 每次间隔都在变小 直到间隔小于小于1停止循环
        while (gap >= 1) {
            for (let i = gap; i < length; i++) {
                let temp = this.array[i]
                let j = i
                while (this.array[j - gap] > temp && j > 0) {
                    this.array[j] = this.array[j - gap] // 9 5 4 3 2 
                    j = j - gap // 停止while循环 以及进行依次比较
                }
                this.array[j] = temp //要是写j-gap的话 那么j的值是一直和i 同步的, 那么相当于你每次都是用下标0 替换的下标gap
            }
            gap = Math.floor(gap / 2)
        }
    }

    // 快速排序获取枢纽  并把枢纽放在数组倒数第二的位置 这样只用找一边的枢纽了?
    this.getPivot = function (left, right) {
        let center = Math.floor((left + right) / 2)
        if (this.array[left] > this.array[center]) {
            this.swap(left, center)
        }
        if (this.array[center] > this.array[right]) {
            this.swap(center, right)
        }
        if (this.array[left] > this.array[center]) {
            this.swap(left, center)
        }

        this.swap(center, right - 1)
        return this.array[right - 1]
    }

    // 快速排序实现 通过递归实现
    this.quickSort = function () {
        // 传入下标值 获取枢纽用
        this.qucikSortRecusion(0, this.array.length - 1)
    }

    // 快速排序的递归
    this.qucikSortRecusion = function (left, right) {
        // 1、中断条件:第一位和最后一位在0处重合 遍历完成。
        if (left >= right) return

        // 2、获得枢纽值
        let pivot = this.getPivot(left, right)

        // 3、进行比较交换
        let i = left
        let j = right - 1 //获取枢纽时最右是大于枢纽的
        while (i < j) {
            while (this.array[++i] < pivot) {} //从左边开始 获得大于于枢纽的值i
            while (this.array[--j] > pivot) {} //从右边开始 获得小于枢纽的值j
            if (i < j) {
                this.swap(i, j)
            }
        }
        this.swap(i, right - 1) //把最大值 i  倒数放 
        // 4、递归重复操作
        this.qucikSortRecusion(left, i - 1)
        this.qucikSortRecusion(i + 1, right)
    }
}

let arr = new arrayList()
arr.append(12)
arr.append(45)
arr.append(24)
arr.append(4)
arr.append(66)
arr.append(22)
arr.append(76)
arr.append(8)
arr.append(99)
arr.append(100)
arr.append(500)
console.log(arr.toString())

总结:
1、冒泡排序是先找出最大元素 length需要动态--
2、选择排序是先找出最小元素 选择排序第一次找出最小值和下标0交换,第二次用最小值与其他数进行比较
3、插入排序,把第一个元素看为局部有序,第二个元素比较进行排序后移。 循环
4、希尔排序要点,间隔。 比如1-9 那就是9比7,7比5... 每次比较都需要再减去间隔
5、快速排序,找出数组的中位数,作为枢纽放在倒数第二位;利用递归,分成两个局部有序,再进行排序
6、通常情况下快速排序>希尔排序>=插入排序>=选择排序>冒泡排序
7、外层循环的作用是再循环内部循环

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容