美文网首页前端笔记
基本数据结构和查找算法

基本数据结构和查找算法

作者: faremax | 来源:发表于2017-10-02 20:39 被阅读11次

    本文包括简单的数据结构和查找算法,属于个人整理。
    初学编程可以用这里的东西联系一下,看一看也挺有意思
    博主个人不认为js中算法数据结构不重要,毕竟这是程序开发的基本功。
    本文还会根据博主学习进展和时间安排不定期更新

    数据结构部分

    列表

    function List(){
      this.listSize = 0;
      this.pos = 0;
      this.dataStore = [];
    
      //查找
      this.find = function(element){
        return dataStore.indexOf(element);
      };
    
      //追加元素
      this.append = function(element){
        this.dataStore[this.listSize++] = element;
      };
    
      //删除元素
      this.remove = function(element){
        var foundAt = this.find(element);
        if(foundAt > -1){
          this.dataStore.splice(foundAt, 1);
          --this.listSize;
          return true;
        }
        return false;
      };
    
      //得到长度
      this.getLength = function(){
        return this.listSize;
      };
    
      //插入元素
      this.insert = function(element, after){
        var insertPos = this.find(after);
        if(insertPos > -1){
          this.dataStore.splice(insertPos+1, 0, element);
          ++this.listSize;
          return true;
        }
        return false;
      };
    
      //清空列表
      this.clear = function(){
        delete this.dataStore;
        this.dataStore.length = 0;
        this.listSize = this.pos = 0;
      };
    
      //判断是否包含某元素
      this.contains = function(element){
        return this.find(element) !== -1;
      };
    
      //转换为字符串
      this.toString = function(){
        return this.dataStore.join(",");
      };
    
      //把指针移到最前
      this.front = function(){
        this.pos = 0;
      };
    
      //把指针移到最后
      this.end = function(){
        this.pos = this.listSize - 1;
      };
    
      //前移指针
      this.prev = function(){
        if(this.pos > 0)
          --this.pos;
      };
    
      //后移指针
      this.next = function(){
        if(this.pos < this.listSize - 1)
          ++this.pos;
      };
    
      //得到指针当前位置
      this.currPos = function(){
        return this.pos;
      };
    
      //把指针移到posi
      this.moveTo = function(posi){
        if(posi < this.listSize && posi >= 0){
            this.pos = position;
            return true;
        }
        return false;
      };
    
      //得到当前指针位置元素
      this.getElement = function(){
        return this.dataStore[this.pos];
      };
    }
    

    队列

    function queue(){
      this.dataStore = [];
    
      this.enqueue = function(element){    //入队
        this.dataStore.push(element);
      };
      this.dequeue = function(){    //出对
        return this.dataStore.shift();
      };
      this.front(){   //查看队首
        return this.dataStore[0];
      };
      this.back(){   //查看队尾
        return this.dataStore[this.dataStore.length - 1];
      };
      this.empty = function(){   //清空队列
        return this.dataStore.length === 0;
      };
      this.getLength = function(){   //得到队列长度
        return this.dataStore.length;
      };
    }
    

    function Stack(){
      this.dataStore = [];
    
      this.push = function(element){   //入栈
        this.dataStore.push(element);
      };
      this.peek = function(){    //查看栈顶
        if(this.dataStore.length > 0)
          return this.dataStore[this.dataStore.length - 1];
        return undefined;
      };
    
      this.clear = function(){   //清空
        this.dataStore.length = 0;
      };
    
      this.pop = function(){    //出栈
        return this.dataStore.pop();
      };
    
      this.getLength = function(){   //得到长度
        return this.dataStore.length;
      };
    }
    

    链表

    function Node(element){      //链表节点
      this.element = element;
      this.next = null;
    }
    function LList(){
      this.head = new Node("head");
    
      this.find = function(item){   //查找
        var currNode = this.head;
        while(currNode && currNode.element != item){
          currNode = currNode.next;
        };
        return currNode;
      };
    
      this.insert = function(newElement, item){    //在item之后插入
        var newNode = new Node(newElement);
        var current = this.find(item);
        if(current === null) {
          this.append(newElement);
          return false;
        }
        newNode.next = current.next;
        current.next = newNode;
        return true;
      };
    
      this.display = function(){   //输出列表
        var currNode = this.head;
        while(currNode.next !== null){
          console.log(currNode.next.element);
          currNode = currNode.next;
        }
      };
    
      this.remove = function(element){
        var currNode = this.head;
        while(1){
          if(currNode.next === null) return false;
          if(currNode.next.element === element) break;
          currNode = currNode.next;
        }
        currNode.next = currNode.next.next;
      };
    }
    

    环形链表

    function Node(element){      //链表节点
      this.element = element;
      this.next = null;
    }
    function LList(){
      this.head = new Node("head");
      this.head.next = this.head;  //成环
    
      this.find = function(item){  //查找
        var currNode = this.head;
        while(currNode.element != item){
          if(currNode.next === this.head) return null;
          currNode = currNode.next;
        };
        return currNode;
      };
    
      this.insert = function(newElement, item){   //在item之后插入
        var newNode = new Node(newElement);
        var current = this.find(item);
        newNode.next = current.next;
        current.next = newNode;
      };
    
      this.display = function(){   //输出列表
        var currNode = this.head;
        while(currNode.next !== this.head){
          console.log(currNode.next.element);
          currNode = currNode.next;
        }
      };
    
      this.remove = function(element){    //删除
        var currNode = this.head;
        while(1){
          if(currNode.next == this.head) return false;
          if(currNode.next.element == element) break;
          currNode = currNode.next;
        }
        currNode.next = currNode.next.next;
      };
    }
    

    双向链表

    function Node(element){
      this.element = element;
      this.next = null;
      this.previous = null;
    }
    function LList(){
      this.head = new Node("head");
      this.tail = this.head;
    
      this.find = function(item){   //查找
        var currNode = this.head;
        while(currNode.element != item){
          if(currNode.next === null) return null;
          currNode = currNode.next;
        };
        return currNode;
      };
    
      this.insert = function(newElement, item){   //在item之后插入
        var newNode = new Node(newElement);
        var current = this.find(item);
        newNode.next = current.next;
        current.next = newNode;
        current.next.previous = newNode;
        newNode.previous = current;
      };
    
      this.display = function(){   //输出列表
        var currNode = this.head;
        while(currNode.next !== null){
          console.log(currNode.next.element);
          currNode = currNode.next;
        }
      };
    
      this.remove = function(item){   //删除
        var currNode = this.find(item);
        if(currNode){
          currNode.previous.next = currNode.next;
          currNode.next.previous = currNode.previous;
          currNode.next = null;
          currNode.previous = null;
          return true;
        }
        return false;
      };
    
      this.dispReverse = function(){   //反向输出
        var currNode = this.tail;
        while(currNode.previous !== null){
          console.log(currNode.element);
          currNode = currNode.previous;
        }
      };
    }
    

    字典

    function dictionary(){
      this.dataStore = [];
    
      this.add = function(key, value){  //插入
        if(this.find(key)) console.log("'" + key + "' exists");
        else this.dataStore[key] = value;
      };
    
      this.find = function(key){   //查找
        return this.dataStore[key];
      };
    
      this.remove = function(key){   //删除
        delete this.dataStore[key];
      };
    
      this.showAll = function(){   //有序输出
        var keys = Object.keys(this.dataStore).sort();
        keys.forEach(function(key){
          console.log(key + " -> " + this.dataStore[key]);
        });
      };
    
      this.count = function(){   //计数
        return Object.keys(this.dataStore).length;
      };
    
      this.clear = function(){   //清除
        for(var k in this.dataStore){
          if(dataStore.hasOwnPorperty(k)){
            delete this.dataStore[k];
          }
        }
      };
    }
    

    集合

    function Set(){
      if(arr){
        this.arr = arr.filter(function(item, index) {
          return arr.indexOf(item) === index;
        });
      } else {
        this.arr = [];
      }
    }
    Set.prototype.constructor = Set;
    
    Myset.prototype.sort = function(fun){  //排序
      this.arr.sort(fun);
      return this;
    };
    
    Set.prototype.add = function(data){   //添加
      if(this.dataStore.indexOf(data) < 0){
        this.dataStore.push(data);
      }
      return this;
    };
    
    Set.prototype.show = function(){  //输出
      console.log(this.dataStore.join(","));
      return this;
    };
    
    Set.prototype.remove = function(data){   //删除
      var pos = this.dataStore.indexOf(data);
      if(pos > -1){
        this.dataStore.splice(pos, 1);
      }
      return this;
    };
    
    Set.prototype.size = function(){  //得到当前集合大小(元素数量)
      return this.dataStore.length;
    };
    Set.prototype.contains = function(data) {    //是否包含data
      return this.dataStore.indexOf(data) > -1;
    };
    
    Set.prototype.clone = function(){   //复制当前集合
      var tempSet = new Set();
      for(var i = 0; i < this.size(); ++i)
        tempSet.add(this.dataStore[i]);
      return tempSet;
    };
    
    Set.prototype.union = function(set){   //求并集
      var tempSet = this.clone();
      for(var i = 0; i < set.size(); ++i){
        if(!tempSet.contains(set.dataStore[i]))
          temp.dataStore.push(set.dataStore[i]);
      }
      return tempSet;
    };
    
    Set.prototype.interSect = function(set){   //求交集
      var tempSet = new Set();
      for(var i = 0; i < this.size(); ++i){
        if(set.contains(this.dataStore[i]))
          tempSet.add(this.dataStore[i]);
      }
      return tempSet;
    };
    
    Set.prototype.subSet = function(set){    //判断当前集合是否set的子集
      if(this.size() > set.size()) return false;
      else{
        for(var i = 0; i < this.size(); ++i){
          if(!set.contains(this.dataStore[i]))
            return false;
        }
      }
      return true;
    };
    
    this.difference = function(set){   //求差集 this-set
      var tempSet = new Set();
      for(var i = 0; i < this.dataStore.length; ++i){
        if(!set.contains(this.dataStore[i]))
          tempSet.add(this.dataStore[i]);
      }
      return tempSet;
    };
    

    哈希表

    function HashTable(){
      this.table = [];
    
      //this.values = [];
    
      //当key是整数的时候可以简单的使用simpleHash
      this.simpleHash = function(data){   //这个函数下文不会用到
        var total = 0;
        for(var i = 0; i < data.length; ++i)
          total += data.charDodeAt(i);
        return total % this.table.length;
      };
    
      //simpleHash()有一个严重的问题:不同字符串可能得到相同hash码,比如"Raymond"和"Clayton"。 这叫做哈希碰撞(hashing collision)
    
      this.betterHash = function(string, arr){
        const H = 31;    //引入一个质数
        var total = 0;
        for(var i = 0; i < string.length; ++i)
          total += H * total + string.charCodeAt(i);
        total = total % arr.length;
        return parseInt(total);
      };
    
    
      this.showDistro = function(){
        var n = 0;
        for(var i = 0; i < this.table.length; ++i){
          // if(this.table[i] !== undefined)      //线性探针法使用这个if
          if(this.table[i][0] !== undefined)    //散列法使用这个if
            console.log(i + ": " + this.table[i]);
        }
      };
    
      //即使使用了betterHash,也不能保证在所有输入中不会一重复的输出,因此产生了散列法(separate chaining)和线性探针法(linear probing)
      //建立散列
      this.buildChains = function(){
        for(var i = 0; i < this.table.length; ++i)
          this.table[i] = [];
      };
    
      //散列法对应put函数
      this.put = function(data){
        var pos = this.betterHash(data);
        var index = 0;
    
        if(this.table[pos][index] === undefined)
          this.table[pos][index] = data;
        else {
          while(this.table[pos][index] !== undefined) ++index;
          this.table[pos][index] = data;
        }
      };
    
      //散列法对应get函数
      this.get = function(key){
        var pos = this.betterHash(key);
        var index = 0;
        if(this.table[pos][index] === key)
          return this.table[pos][index + 1];
        else {
          while(this.table[pos][index] !== key) index += 2;
          return this.table[pos][index + 1];
        }
        return undefined;
      };
    
      /*
      //线性探针法对应put函数
      this.put = function(key, data){
        var pos = this.betterHash(data);
        if(this.table[pos] == undefined){
          this.table[pos] = key;
          this.values[pos] = data;
        } else {
          while(this.table[pos] != undefined) ++pos;
          this.table[pos] = key;
          this.values[pos] = data;
        }
      };
    
      //线性探针法对应get函数
      this.get = function(key){
        var hash = -1;
        hash = this.betterHash(key);
        if(hash > -1){
          for(var i = hash; this.table[hash] != undefined; ++i){
            if(this.table[hash] == key)
              return this.values[hash];
          }
        }
      };
      */
    }
    

    function Node(data, left, right){   //树节点
      this.data = data;
      this.left = left;
      this.right = right;
      this.show = function(){ return this.data; };
    }
    
    //建立一个二叉查找树(Binary Search Tree)
    function BST(){
      this.root = null;
    
      this.insert = function(data){
        var n = new Node(data, null, null);
        if(this.root === null) {
          this.root = n;
        }
        else{
          var current = this.root;
          var parent;
          while(true){
            parent = current;
            if(data < current.data){
              current = current.left;
              if(current === null){
                parent.left = n;
                break;
              }
            }
            else{
              current = current.right;
              if(current == null){
                parent.right = n;
                break;
              }
            }
          }
        }
      };
    
      //中序遍历
      this.inOrder = function(node){
        if(node !== null){
          inOrder(node.left);
          console.log(node.show() + " ");
          inOrder(node.right);
        }
      };
    
      //前序遍历
      this.preOrder = function(node){
        if(node !== null){
          console.log(node.show() + " ");
          preOrder(node.left);
          preOrder(node.right);
        }
      };
    
      //后序遍历
      this.postOrder = function(node){
        if(node !== null){
          postOrder(node.left);
          postOrder(node.right);
          console.log(node.show() + " ");
        }
      };
    
      //得最小值
      this.getMin = function(){
        var current = this.root;
        while(current.left !== null)
          current = current.left;
        return current.data;
      };
    
      //得最大值
      this.getMax = function(){
        var current = this.root;
        while(current.right !== null)
          current = current.right;
        return current.data;
      };
    
      //查找值
      function find(data){
        var current = this.root;
        while(current !== null){
          if(current.data == data) return current;
          else if(data < current.data) current = current.left;
          else if(data > current.data) current = current.right;
        }
        return null;
      };
    
      //删除值
      this.removeData = function(data){
        this.root = removeNode(this.root, data);
        function removeNode(node, data){
          if(node === null) return null;
          if(data === node.data){
            if(node.left == null && node.right == null) return null;
            if(node.left == null) return node.right;
            if(node.right == null) return node.left;
            var tempNode = getSmallest(node.right);
            node.data = tempNode.data;
            node.right = removeNode(node.right, tempNode.data);
            return node;
          }
          else if(data < node.data){
            node.left = removeNode(node.left, data);
            return node;
          } else{
            node.right = removeNode(node.right, data);
            return node;
          }
        }
      };
    }
    

    function Graph(v_num){
      this.vertices = v_num;    //定点数量
      this.edges = 0;       //边的数量
      this.adj = [];        //邻接矩阵
      this.marked = [];     //用于遍历时标记已遍历的点
      this.vertexList = []; //存放顶点
      this.edgeTo = [];     //在寻找最短路径时,存放轨迹
    
      for(var i = 0; i < this.vertices; ++i){    //初始化邻接矩阵
        this.adj[i] = [];
        this.adj[i] = push("");
      }
    
      this.addEdge = function(v, w){   //添加边,传入2个点
        this.adj[v].push(w);
        this.adj[w].push(v);
        this.edges++;
      };
    
      this.showGraph = function(){    //输出图
        for(var i = 0; i < this.vertices; ++i){
          console.log(i + " -> ");
          for(var j = 0; j < this.vertices; ++j){
            if(this.adj[i][j] !== undefined)
              console.log(this.adj[i][j] + " ");
          }
          console.log("\n");
        }
      };
    
      //深度优先遍历
      this.dfs = function(v){
        for(var i = 0; i < this.vertices; ++i)   //初始化标记矩阵
          this.mark[i] = false;
        innerDfs(v);
    
        function innerDfs(v){
          this.marked[v] = true;
          if(this.adj[v] !== undefined)
            console.log(v + " ");
          for(var i = 0; i < this.adj[v].length; ++i){
            var ver = this.adj[v][i];
            if(!this.marked[ver]) this.innerDfs(ver);
          }
        }
      };
    
      //广度优先遍历
      this.bfs = function(s){
        for(var i = 0; i < this.vertices; ++i)   //初始化标记矩阵
          this.mark[i] = false;
        var queue = [];     //存放访问过的节点
        this.marked[s] = true;
        queue.push(s);
        while(queue.length > 0){
          var v = queue.shift();
          if(v !== undefined) console.log(s + "");
          for(var i = 0; i < this.adj[v].length; ++i){
            var ver = this.adj[v][i];
            if(!this.marked[ver]){
              this.edgeTo[ver] = v;
              this.marked[ver] = true;
              queue.push(ver);
            }
          }
        }
      };
    
      this.hasPathTo = function(v){   //判断是否有到节点v的路径
          return this.marked[v];
      };
    
      this.showPath = function(){     //显示路径
        while(paths.length > 0){
          if(paths.legnth > 1) console.log(paths.pop() + '-');
          else console.log(paths.pop());
        }
      };
    
      this.pathTo = function(v) {    //计算path路径
        var path = [];
        var source = 0;
        if(!this.hasPathTo(v))
          return undefined;
        for(var i = v; i !== source; i = this.edgeTo[i])
          path.push(i);
        path.push(source);
        return path;
    
      };
    
      //拓扑排序
      this.topologicalSort = function(){
    
        var stack = [];     //栈
        var visited = [];   //记录已访问节点
        //初始化
        for(var i = 0; i < this.vertices; ++i)
          visited = false;
    
        for(var i = 0; i < this.vertices; ++i){
          if(!visited[i])
            this.topSortHelper(i, visited);  //排列没有访问过的节点
        }
    
        for(var i = 0; i < stack.length; ++i){
          if(stack[i] !== undefined && stack[i] !== false)
            console.log(this.vertexList[stack[i]]);
        }
    
        function topSortHelper(v, visited){
          visit[v] = true;
          for(var i = 0; i < this.adj[v].length; ++i){
            var w = this.adj[v][i];
            if(!visited[w])
              this.topSortHelper(visited[w], visited);  //递归当前节点的相邻节点
          }
          stack.push(v);
        }
      };
    }
    

    查找相关算法

    顺序查找

    function seqSearch(arr, data){
      for(var i = 0; i < arr.length; i++){
        if(arr[i] == data) return i;
      }
      return -1;
    }
    

    二分查找

    //数组arr应该已升序排列
    function binSearch(arr, data){
      var upperBound = arr.length - 1;
      var lowerBound = 0;
      while(lowerBound <= upperBound){
        var mid = Math.floor((upperBound + lowerBound) / 2);
        if(arr[mid] < data) lowerBound = mid + 1;
        if(arr[mid] > data) upperBound = mid - 1;
        if(arr[mid] == data) return mid;
      }
      return -1;
    }
    
    //利用二分查找计数
    //数组arr应该已升序排列
    function count(arr, data){
      var count = 0;
      var pos = binSearch(arr, data);
      if(pos > -1){
        ++count;
        for(var i = pos - 1; i > 0; --i){
          if(arr[i] == data) ++count;
          else break;
        }
        for(var i = pos + 1; i < arr.length; ++i){
          if(arr[i] == data) ++count;
          else break;
        }
      }
      return count;
    }
    

    二叉查找树

    在本文数据结构部分——树的部分已经实现

    哈希查找

    在本文数据结构部分——哈希表部分的get()方法已经实现

    插值查找

    function insertionSearch(arr, value){
      return insertionSearchHelper(arr, value, 0, arr.length);
    
      function insertionSearchHelper(arr, value, low, high){
        var mid = low + (value - arr[low]) / (arr[high] - arr[low]) * (high - low);
    
        if(arr[mid] === value)
          return mid;
        if(arr[mid] > value)
          return InsertionSearchHelper(arr, value, low, mid-1);
        if(arr[mid] < value)
          return InsertionSearchHelper(arr, value, mid+1, high);
        return null;
      }
    }
    

    整理所有查找算法时间复杂度

    算法 查找(最坏) 插入(最坏) 删除(最坏) 查找(最好) 插入(最好) 删除(最好) 是否要求有序
    顺序结构 N N N N/2 N N/2 No
    二分算法 logN N N logN N/2 N/2 Yes
    二叉查找树(BST) N N N 1.39logN 1.39logN √N Yes
    2-3树 clogN clogN clogN clogN clogN clogN Yes
    红黑树 2logN 2logN 2logN logN logN logN Yes
    哈希散列查找 logN logN logN 3~5 3~5 3~5 No
    哈希探针查找 logN logN logN 3~5 3~5 3~5 No

    平均查找长度(ASL) = 查找表中第 i 个元素概率(Pi) * 找到第 i 个元素时已经比较的次数(Ci)

    相关文章

      网友评论

        本文标题:基本数据结构和查找算法

        本文链接:https://www.haomeiwen.com/subject/zyityxtx.html