JS---实现数据结构/排序算法

13 篇文章 0 订阅
1 篇文章 0 订阅

排序算法

冒泡排序O(n^2)

前往后后依次比较相邻两个元素大小,大的元素往后挪,比较完第一遍后,最大的元素排到了数组的最后一位

  1. 从第1个数字比较与最后一个数字,结束时最大的位于最后;
  2. 第二轮比较到倒数第二个
  3. 最后一轮比较第1,2个;
    在这里插入图片描述
    mSort(arr);
    function mSort(a){
        for(var i=0;i< a.length;i++){
            for(var j=i;j< a.length;j++){
                if(a[j]<a[i]){
                    var temp=a[i];
                    a[i]=a[j];
                    a[j]=temp;
                }
            }
        }
        console.log(a);
    }

快速排序O(nlog(n))

快速排序的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据比另一部分的所有数据要小,再按这种方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,使整个数据变成有序序列。

  1. 取出中间一个数centernum(原数组不保留)
  2. 比centernum小的放入数组left,比centernum大的放入right数组
  3. left right 进行快速排序递归
  4. arr=left+centernum+right
  qSort(arr);
    function qSort(a){
        if(a.length<2){
            return;
        }
        var left=[];
        var right=[];
        //找中间索引centerIndex  取出中间数centerNum
        var centerIndex=a[parseInt(a.length/2)];
        var centerNum=a.splice(centerIndex,1);
        for(var i=0;i< a.length;i++){
            //a[i]<=centernum 放入数组left,a[i]>centernum放入right数组
            if(a[i]<=centerNum){
                left.push(a[i]);
            }else{
                right.push(a[i]);
            }
        }
        return qSort(left).concat(centerNum).concat(qSort(right));
        console.log(arr);
    }

插入排序O(n^2)

插入排序的基本操作:将一个数据插入到已经排好序的有序数据中。

  1. 从第i(2)个数开始插入排序
  2. 逆序与前面所有的数(i-1~1)进行比较,小的数互换到前面去

算法适用于少量数据的排序
在这里插入图片描述

    insertSort(arr);
function insertSort(a){
    //从第i个数插入排序
    for(var i=1 ;i<a.length;i++){
        //与i-1往前比较,a[i]<a[j]互换
        for(var j=i-1;j>=0;j--){
            if(a[j]>a[i]){
                var temp=a[i];
                a[i]=a[j];
                a[j]=temp;
            }
        }
    }
    console.log(arr);
}

选择排序O(n^2)

在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止(假设为从小到大排序)

  1. 对数组中所有数值进行比较,获得最小值下标,然后将最小值与第一个数交换
  2. 对数组中剩余(除第一个数)数值进行比较,获得最小值下标,然后将最小值与第二个数交换
  3. 直至确定倒数第二个位置的数值
    在这里插入图片描述
    seleSort(arr);
function seleSort(a){
    for (var i=0;i< a.length;i++){
        var minNum=a[i];
        for(var j=i;j< a.length;j++){
            if(a[j]<a[i]){
                minNum=a[j];
                a[j]=a[i];
                a[i]=minNum
            }
        }
    }
    console.log(a);
}

算法复杂度

大O表示法的概念。是描述算法的性能和复杂程度。
在这里插入图片描述

在这里插入图片描述

数据结构

栈是一种遵从先进后出 (LIFO) 原则的有序集合;新添加的或待删除的元素都保存在栈的末尾

class Stack {

    constructor() {
        this.items = []
    }

    // 入栈
    push(element) {
         this.items.push(element)
    }

    // 出栈
    pop() {
        return this.items.pop()
    }

    // 末位
    get peek() {
        return this.items[this.items.length - 1]
    }

    // 是否为空栈
    get isEmpty() {
        return !this.items.length
    }

    // 尺寸
    get size() {
        return this.items.length
    }

    // 清空栈
    clear() {
        this.items = []
    }

    // 打印栈数据
    print() {
        console.log(this.items.toString())
    }
}

队列

队列是一种遵循先进先出 (FIFO / First In First Out) 原则的一组有序的项;队列在尾部添加新元素,并从头部移除元素。

class Queue {

    constructor(items) {
        this.items = items || []
    }

    enqueue(element){
        this.items.push(element)
    }

    dequeue(){
        return this.items.shift()
    }

    front(){
        return this.items[0]
    }

    clear(){
        this.items = []
    }

    get size(){
        return this.items.length
    }

    get isEmpty(){
        return !this.items.length
    }

    print() {
        console.log(this.items.toString())
    }
}

单项链表

在这里插入图片描述

// 链表节点
class Node {
    constructor(ele) {
        this.element = ele
        this.next = null
    }
}
// 链表
class LinkedList {
    constructor() {
        this.head = null  //
        this.length = 0	  //长度
    }
    
    // 最后追加元素
    append(element) {
    	//1. 创建新节点
        const node = new Node(element)	
        //2.判断添加的是否第一个节点
        if (this.head === null) { //this.length == 0  2.1 是第一个节点
            this.head = node
        } else {				//2.2 不是第一个节点,找最后一个节点
           var current = this.head
            while(current.next) {
                current = current.next
            }
            current.next = node	//2.2.1最后一个节点指向新节点
        }
        //3. length + 1
        this.length++
    }
    // 任意位置插入元素
    insert(position, element) {		 //1.位置边界判断 0-length
        if (position >= 0 && position <= this.length) {
            const node = new Node(element)//创建新节点
            let current = this.head	//当前节点
            let previous = null//先前节点
            let index = 0//当前位置    
            if (position === 0) {	//2.1位置是第一个        
                this.head = node
            } else { 				//2.2位置不是第一个
                while (index++ < position) {  //2.2.1找到当前位置,右移节点
                    previous = current 			//当前节点→前节点
                    current = current.next 		//下一节点→当前节点
                }
                node.next = current		//新节点.next = 当前节点
                previous.next = node	//前节点.next = 新节点
            }//3. 长度加一
            this.length++
            return true
        }
        return false
    }

    // 移除指定位置元素
    removeAt(position) {       // 1.检查越界值 0-length-1
        if (position > -1 && position < this.length) {  //null不能删除
            let current = this.head	//当前节点,current.next下一个节点
            let previous = null	//前一个节点
            let index = 0	//当前位置
            if (position === 0) {	//2.1删除位置为0
                this.head = current.next	//head指向 下一个节点
            } else {				//2.2删除位置不为0
                while (index++ < position) {  //2.2.1找到当前位置,右移节点
                    previous = current		//当前节点→前节点
                    current = current.next	//下一节点→当前节点
                }
                previous.next = current.next	//前节点.next = 当前节点.next
            }
            this.length--	//3.长度--
            return current.element  //返回长度
        }
        return null
    }
    // 删除指定元素
    remove(element) {
        const index = this.findIndex(element)
        return this.removeAt(index)
    }

    //修改指定位置元素
    update(position,newEle){
		if (position < -1 || position >= this.length)  return false
		let index= 0
		let current = this.head
		while(index++<position){	//2.查找正确节点
			current = current.next //右移
		}
		current.element = newEle //3.修改节点
		return true
	}        
	//获取相应位置元素
	get(position){
	 	if (position < -1 || position >= this.length)  return false
		let index= 0
		let current = this.head
		while(index++<position){
			current = current.next //右移
		}
		return current.element
	}
    // 寻找元素下标
    findIndex(element) {
        let current = this.head
        let index = 0
        while (current) {//开始查找
            if (element === current.element) {
                return index 
            }
            index++
            current = current.next  //右移
        }
        return -1
    }
    // 转为字符串
    toString() {
        let current = this.head
        let string = ''
        while (current) {
            string += ` ${current.element}`  //凭借当前节点
            current = current.next			//节点右移
        }
        return string
    }
    isEmpty() {
        return !this.length
    }

    size() {
        return this.length
    }
}

反转链表

1>2>3>4>5 反转为
1.取新的头结点reverseHead
2.遍历原链表,去除链表节点将其放到reverseHead新链表最前端
3. this.head = reverseHead.head;

    //反转链表,返回新链表
    reverseHead (){        
        if(this.length <=1 ){ //空节点,一个节点
            return	curr;
        }
        var reverseHead = new LinkedList();		//1.新头结点      
        let curr = this.head;       //原链表结点1
        let next = null;            //原链表结点2
        //2.遍历原链表,去除链表节点将其放到reverseHead新链表最前端
        while(curr){
            next = curr.next; //暂时保存下一个节点
            curr.next = reverseHead.head;  //下一个节点 连接 保存到前端
            reverseHead.head = curr;            
            curr = next;  //curr后移
        }
        3. this.head = reverseHead.head;
         this.head = reverseHead.head;
         reverseHead.length = this.length;
        return	reverseHead ;
    }

双项链表

在这里插入图片描述

// 双向链表节点
class Node {
    constructor(element) {
        this.element = element
        this.prev = null
        this.next = null
    }
}
// 双向链表
class DoublyLinkedList {
    constructor() {
        this.head = null
        this.tail = null
        this.length = 0
    }

    // 任意位置插入元素
    insert(position, element) {
        if (position >= 0 && position <= this.length){  //1.越界判断
            const node = new Node(element)
            let current = this.head		//当前位
            let previous = null			//先前位
            let index = 0
             if (!head){  //当前长度为0  this.length==0		//2.为空
                    this.head = node
                    this.tail = node
                } else {	//当前长度不为0		//3.不为空		 														
		            if (position === 0) {       // 3.1 首位插入	 
		            		current.prev = node    //nextNode.prev   
		                    node.next = current		//node.next		                    
		                    this.head = node		// → node
		                }		            
		            } else if (position === this.length) {// 3.2 末位
		                current = this.tail		//找到当前最后位
		                current.next = node		//当前位.next = node
		                node.prev = current		//node.prev = 当前位
		                this.tail = node		//最后位更新            
		            } else {						// 3.3中位
		                while (index++ < position) {//3.3.1找到对应位置
		                    previous = current		//先前位右移
		                    current = current.next	//当前位右移
		                }
		                node.next = current			//node.next
		                previous.next = node
		                current.prev = node
		                node.prev = previous		//node.prev
		            }
		            this.length++
		            return true
		        }			
				}
           
        return false
    }
    // 末位插入元素 追加元素
    append(element){
            let current = this.head
            let previous = null
			if(this.length == 0){  //1.元素为空
                    this.head = node
                    this.tail = node
			}else{					//2.元素不为空
			    while(current.next){//2.1右移到末尾
				current = current.next
			}
		        current.next = node		//当前位.next = node
		        node.prev = current		//node.prev = 当前位
		        this.tail = node		//最后位更新 
			}
			
	}
	
    // 移除指定位置元素		---无指向的节点会回收
    removeAt(position) {
        if (position > -1 && position < this.length) {	//1.越界判断
            let current = this.head
            let previous = null
            let index = 0

            // 2.首位移除
            if (position === 0) {
                this.head = this.head.next	//→ node 消失
                this.head.prev = null		// node ← 消失
                if (this.length === 1) {	//只有一个节点,tial → null
                    this.tail = null
                }

            // 3.末位
            } else if (position === this.length - 1) {
                this.tail = this.tail.prev	// node ← tail消失,tial指向prev
                this.tail.next = null		//钱洁典  = null

            // 4.中位
            } else {
                while (index++ < position) { //右移找到节点
                     previous = current
                     current = current.next
                }
                previous.next = current.next	//→ node 消失,prev = next
                current.next.prev = previous	//  node ←消失, 指向prev
         }
         this.length--
         return current.element
        } else {
            return null
        }
    }

    // 转为字符串(正向)
    toString(){
		let str = ''
		let current = this.head
		while(current){
			str += current.element + " "
			current = current.next
		}
		retyrn str
	}
    // 转为字符串(逆向)
        toForwardString(){
		let str = ''
		let current = this.tail
		while(current){
			str += current.element + " "
			current = current.prev
		}
		retyrn str
	}
}

二叉搜索树

二叉搜索树(BST)是二叉树的一种,但是它只允许你在左侧节点存储(比父节点)小的值, 在右侧节点存储(比父节点)大(或者等于)的值。

class Node {  //树节点
    constructor(key) {
        this.key = key
        this.left = null
        this.right = null
    }
}

class BinarySearchTree {
    constructor() {	//根节点
        this.root = null
    }

    insert(key) {
        const newNode = new Node(key)
        const insertNode = (node, newNode) => {
            if (newNode.key < node.key) {  //1.1小于 & left为空
                if (node.left === null) {
                    node.left = newNode
                } else {		//1.2left不为空,在left递归
                    insertNode(node.left, newNode)
                }
            } else {					//2.1大于 & rigth为空
                if (node.right === null) {
                    node.right = newNode
                } else {		//2.2rigth不为空,在rigth递归
                    insertNode(node.right, newNode)
                }
            }
        }
         if (!this.root) { 		//3.1根节点为空
            this.root = newNode
        } else {				//3.2根节点不为空
            insertNode(this.root, newNode)
        }
    }
    //查找key,返回boolean
    search(key){   
        let node = this.root;  //0.node为根节点开始
        while(node){// 1.node 不为空一直遍历
            if(node.key < key){     //2.1大于右移
                node = node.right;
            }else if(node.key > key){//2.2小于左移
                node = node.left;
            }else{
                return true;
            }
        }
       return false;        
    }
    //查找最值
    
	remove(key){}
}

前序遍历

中序遍历

后序遍历

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值