数据结构(JS版)

冒泡排序

  1. 对未排序的各元素从头到尾依次比较相邻的两个元素大小关系
  2. 如果左边的队员高, 则两队员交换位置
  3. 向右移动一个位置, 比较下面两个队员
  4. 当走到最右端时, 最高的队员一定被放在了最右边
  5. 按照这个思路, 从最左端重新开始, 这次走到倒数第二个位置的队员即可.
  6. 依次类推, 就可以将数据排序完成
function bubbleSort(arr){
	var len = arr.length;
    for(let i = length-1; i>=0; i--){		
        for(let j = 0; j < i; j++){
            if(arr[j]>arr[j+1]){
                [arr[j],arr[j+1]] = [arr[j+1],arr[j]];
            }
        }
    }
    return arr;
}

选择排序

  1. 选定第一个索引位置,然后和后面元素依次比较
  2. 如果后面的队员, 小于第一个索引位置的队员, 则交换位置
  3. 经过一轮的比较后, 可以确定第一个位置是最小的,一共进行n轮(数组长度)
  4. 然后使用同样的方法把剩下的元素逐个比较即可
  5. 可以看出选择排序,第一轮会选出最小值,第二轮会选出第二小的值,直到最后
function selectionSort(arr){
	var len = arr.length;
    for(let i = 0; i<len; i++){			//n趟操作
        let minIndex = i;
        for(let j = i+1; j<len; j++){
            if(arr[j]<arr[minIndex]){
                minIndex = j;
            }
        }
        [arr[minIndex],arr[i]] = [arr[i],arr[minIndex]];
    }
    return arr;
}

插入排序

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取出下一个元素 temp,在已经排序的元素序列中从后向前扫描
  3. 如果已排序的元素大于新元素 temp,将已排序的元素移到下一位置
  4. 重复上一个步骤,直到找到已排序的元素小于或者等于新元素 temp 的位置
  5. 将新元素插入到已排序的元素后, 重复上面的步骤
function insertSort(arr){
    var len = arr.length;
    for(let i = 1; i<len; i++){
        var temp = arr[i];
        var j = i;
        while(j > 0 && arr[j-1] > temp){
            arr[j] = arr[j-1];
            j--;
        }
        [arr[j],temp] = [temp,arr[j]];
    }
    return arr;
}

快速排序

  1. 对于序列A[1]、A[2]、...、A[n],调整序列中元素的位置,使得A[1]的左侧所有元素都不超过A[1],右侧所有的元素都大于A[1]
  2. 一次排序结束后对左右两边元素递归。
function Partition(arr, left, right){
	var temp = arr[left];
    while(left<right){
        while(left < right && arr[right] > temp){
            right--;
        }
        arr[left] = arr[right];
        while(left < right && arr[left] < temp){
            left++;
        }
        arr[right] = arr[left];
    }
    arr[left] = temp;
    return left;
}

function quickSort(arr,left,right){
    if(left<right){
        var pos = Partition(arr,left,right);
        quickSort(arr,left,pos-1);
        quickSort(arr,pos+1,right);
        return arr;
    }
}

归并排序

步骤:

  1. 申请空间,使其大小为两个已排序序列之和,该空间用来存放合并后的序列
  2. 设定两个指针,初始分别为两个已排序序列的起始位置
  3. 比较两个指针指向的元素,选择相对较小的元素加入合并空间,并移动对应的指针到下一位置
  4. 重复步骤 3 直到某一个指针到达序列末尾
  5. 将另一序列剩下的所有元素直接复制到合并序列尾部
function mergeSort(arr){
    var len = arr.length;
    if(len < 2) return arr;
    
    var middle = Math.floor(len / 2),
        left = arr.slice(0, middle),
        right = arr.slice(middle);
    return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right){
    var result = [];
    
    while(left.length && right.length){
        if(left[0] <= right[0]){
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
    }
    while(left.length) result.push(left.shift());
    while(right.length) result.push(right.shift());
    return result;
}

堆排序

堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆(大根堆);或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。

基本思路:

  1. 将待排序序列构建成一个大顶堆,此时整个序列的最大值就是堆顶的根节点
  2. 将堆顶元素与末尾元素交换,将最大元素放到数组末端
  3. 重新调整结构,使其满足堆定义,然后继续交换堆顶元素和末尾元素,重复此步骤直到整个序列有序。
//生成大顶堆
function adjustHeap(arr, i, len){
	//保存当前值
    var temp = arr[i];
    //从i节点的左子节点开始,即2i+1
    for(let j = 2 * i + 1; j < len; j = 2 * j + 1){
        //如果左子结点小于右子结点,j指向右子结点
        if(j+1<len && arr[i] < arr[j+1]){
            j++;
        }
        //如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)值和索引都赋值
        if(arr[j] > temp){
            arr[i] = arr[j];
            i = j;
        } else {
            break;
        }
    }
    arr[i] = temp; //将temp值放到最终的位置
}

function heapSort(data) {
  //构造大顶堆
  //此时我们从最后一个非叶子结点开始,叶结点自然不用调整
  //从第一个非叶子结点从下至上,从右至左调整结构
  for (var i = data.length / 2 - 1; i >= 0; i--) {
    adjustHeap(data, i, data.length);
  }
  // console.log(data);
  //交换堆顶元素与末尾元素;不算最后一个元素,重新调整堆
  for (var k = data.length - 1; k > 0; k--) {
    //将堆顶元素与末尾元素进行交换
    [data[0], data[k]] = [data[k], data[0]];
    // console.log(data);
    //不算最后一个元素,重新对堆进行调整
    adjustHeap(data, 0, k);
  }
  return data;
}

数组模拟栈

function Stack(){
    var items = [];
    
    this.push = (element) => {
       return items.push(element);
    };
    
    this.pop = () => {
       return items.pop();
    };
    //栈顶元素
    this.peek = () => {
       return items[items.length - 1];
    }
    
    this.isEmpty = () => {
       return items.length == 0;
    }
    
    this.size = () => {
       return items.length;
    };
}

进制转换

// 十进制转二进制
function trans(number) {
    var stack = new Stack();
    var remainder;
    
    while(number > 0){
        remainder = number % 2 ;
        number = Math.floor(number / 2);
        stack.push(remainder);
    }
    
    var binaryString = "";
    while(!stack.isEmpty()){
        binaryString += stack.pop();
    }
    return binaryString;
}	

// 使用原生数组实现
function trans(number) {
    var remainder;
    var stack = [];
    
    while(number > 0){
        remainder = number % 2 ;
        number = Math.floor(number / 2);
        stack.push(remainder);
    }
    
    var binaryString = "";
    while(stack.length > 0){
        binaryString += stack.pop();
    }
    return binaryString;
}	

队列

数组模拟队列

function Queue() {
  var items = [];

  // 队列操作的方法
  // enter queue方法
  this.enqueue = function (element) {
    items.push(element);
  };

  // delete queue方法
  this.dequeue = function () {
    return items.shift();
  };

  // 查看前端的元素
  this.front = function () {
    return items[0];
  };

  // 查看队列是否为空
  this.isEmpty = function () {
    return items.length === 0;
  };

  // 查看队列中元素的个数
  this.size = function () {
    return items.length;
  };
}

优先级队列

  • 插入一个元素的时候会考虑该数据的优先级(和其他数据优先级进行比较)。
  • 比较完成后, 可以得出这个元素正确的队列中的位置。 其他处理方式和队列的处理方式一样。
  • 要实现优先级队列, 最主要是要修改添加方法,还需要以某种方式来保存元素的优先级
function PriorityQueue() {
    var items = [];
    
    // 封装一个新的构造函数, 用于保存元素和元素的优先级
    function QueueElement(element, priority){
        this.element = element;
        this.priority = priority;
    };
    
    //添加元素的方法
    this.enqueue = (element, priority)=>{
        // 1.根据传入的元素, 创建新的QueueElement
        var queueElement = new QueueElement(element, priority);
        
        // 2.如果是空队列,直接放入
    	if (this.isEmpty()) {
      		items.push(queueElement);
      		return;
    	}
        // 3.修改传入元素应该所处位置
        if (queueElement.priority < items[0].priority) {
      		// 3.1:如果传入元素权重最高(数字最小),放在队列第一位
      		items.unshift(queueElement);
    	} else if (queueElement.priority > items[items.length -1].priority){
            // 3.2:如果传入元素权重最低(数字最大),放在队列最后一位
      		items.push(queueElement);
        } else {
            // 3.3:传入的元素权重处于中间位置,找到合适的位置并插入
            var start = 0;
            var end = items.length - 1;
            // 二分
            while(start < end) {
                var middle = Math.floor((start + end) / 2);
                var current = items[middle].priority;
                if(queueElement.priority < current){
                    end = middle;
                } else if(queueElement.priority >= current){
                    start = middle;
                }
            }
            items.splice(start, 0, queueElement);
        }
    };
    // 删除元素的方法
    this.dequeue = function () {
    	return items.shift();
  	};
    // 获取前端的元素
	this.front = function () {
    	return items[0];
  	};
    // 查看元素是否为空
  	this.isEmpty = function () {
    	return items.length == 0;
  	};
	// 获取元素的个数
  	this.size = function () {
    	return items.length;
	};
}
// test
// 创建优先级队列对象
var pQueue = new PriorityQueue();

// 添加元素
pQueue.enqueue("abc", 10);
pQueue.enqueue("cba", 5);
pQueue.enqueue("nba", 12);
pQueue.enqueue("mba", 3);

// 遍历所有的元素
var size = pQueue.size();
for (var i = 0; i < size; i++) {
  var item = pQueue.dequeue();
  console.log(item.element + "----" + item.priority);
}
/*
mba----3
cba----5
abc----10
nba----12
*/

链表

//封装
function LinkedList() {
	function Node(element){
        this.element = element;
        this.next = null;
    }
    this.length = 0;
    this.head = null;
    
    // 链表尾部追加元素方法
    LinkedList.prototype.append = (element)=>{
        // 1.根据新元素创建节点
        var newNode = new Node(element);
        
        // 2.判断原来链表是否为空
        if(this.head === null){
            this.head = newNode;
        } else {
            var current = this.head;
            while (current.next) {
                current = current.next;
            }
            //找到最后一项, 将其next赋值为newNode
            current.next = newNode;
        }
        
        this.length++;
    };
    
    //链表元素转化为字符串
    Linkedlist.prototype.toString = ()=>{
        var current = this.head;
        var listString = "";
        
        while(current){
            listString += "," + current.element;
            current = current.next;
        }
        return listString.slice(1);
    }
    
    //根据下标插入元素
    LinkedList.prototype.insert = (position, element) => {
        if(position < 0 || position > this.length) return false;
        // 2.定义变量, 保存信息
        var newNode = new Node(element);
        var current = this.head;
        var previous = null;
        index = 0;
        
        // 3.判断是否列表是否在第一个位置插入
        if(position == 0){
            newNode.next = current;
            this.head = newNode;
        }else{
            while(index++ < position){
                previous = current;
                current = current.next;
            }
            newNode.next = current;
            previous.next = newNode;
        }
        
        this.length++;
        return true;
    };
    
    //根据位置移除节点
    LinkedList.prototype.removeAt = (position) =>{
        // 1.检测越界问题: 越界移除失败, 返回null
        if(position < 0 || position > this.length) return null;
        
        // 2.定义变量
        var current = this.head;
        var previous = null;
        var index = 0;

        //3.判断是否是移除第一项
        if(position == 0){
            this.head = current.next;
        }else{
            while(index++ < position){
        		previous = current;
                current = current.next;
            }
            previous.next = current.next;
        }
        this.length--;
        
        // 4.返回移除的数据
 	    return current.element;
    };
    
    // 根据元素获取链表中的位置
    LinkedList.prototype.indexOf = function (element) {
    	// 1.定义变量, 保存信息
    	var current = this.head;
	    index = 0;

	    // 2.找到元素所在的位置
    	while (current) {
      		if (current.element === element) {
        		return index;
		    }
	        index++;
      		current = current.next;
    	}

    	// 3.来到这个位置, 说明没有找到, 则返回-1
    	return -1;
  	};
    
	// 根据元素删除信息
  	LinkedList.prototype.remove = function (element) {
    	var index = this.indexOf(element);
    	return this.removeAt(index);
  	};

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

  	// 获取链表的长度
  	LinkedList.prototype.size = function () {
    	return this.length;
  	};

  	// 获取第一个节点
  	LinkedList.prototype.getFirst = function () {
    	return this.head.element;
  	};	
}

定义

function TreeNode(x){
    this.val = x;
    this.left = null;
    this.right = null;
}

前序遍历

递归
function preOrder(root) {
  let res = [];
  function __preOrder(root) {
    if (!root) return null;
    res.push(root.val);
    __preOrder(root.left);
    __preOrder(root.right);
  }
  __preOrder(root);
  return res
}
非递归
function preOrder(root) {
  if (!root) return null;
  let nodes = [];
  let res = [];
  nodes.push(root);
  while(nodes.length) {
    let node = nodes.pop();
    res.push(node.val);
    node.right && nodes.push(node.right);
    node.left && nodes.push(node.left);
  }
  return res
}
测试
          		1
            /       \
          2           3
        /   \      /     \
      4       5   6       7
let root = {
  val: 1,
  left: {
    val: 2,
    left: {
      val: 4,
      left: null,
      right: null
    },
    right: {
      val: 5,
      left: null,
      right: null
    }
  },
  right: {
    val: 3,
    left: {
      val: 6,
      left: null,
      right: null
    },
    right: {
      val: 7,
      left: null,
      right: null
    }
  }
}

console.log(preOrder(root)); // [1, 2, 4, 5, 3, 6, 7]

最长连续等于target的子序列

//滑动窗口
function solution(arr, target) {
    let i = 0;
    let j = 0;
    let sum = arr[0];
    while(i <= j && i < arr.length - 1){
        if(sum === target){
            return arr.slice(i, j + 1);
        } else if(sum < target) {
            sum += arr[++j];
        } else {
            sum -= arr[i++];
        }
    }
    return false;
}

console.log(solution([3, 2, 1, 5, 4, 3, 7, 9], 12));
// 输出[2,1,5,4]
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

eynoZzzzc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值