javascript數據結構與算法 --- 棧 vs 隊列 vs 鏈表 vs 二叉樹 vs 圖

數據結構

前言

隨着node的興起, 將javascript推向的一個史無前例的高度, node做爲爲創建高性能的服務端而建立的js運行平臺隨着時間的推移和生態鏈的完善已經再也不局部於服務端,包括前端,後端,桌面......
正如Jeff Atwood在2007年提出的:任何能夠使用JavaScript來編寫的應用,最終會由JavaScript編寫, 雖然人們大多或多或少對筆者的文章有點斷章取義, 但無可變非的是javascript正在大行其道 ^_^,
但正如偉大的js之父親布蘭登.艾奇--(往往想起他和 冰與火之歌中史塔克家族什麼關係 哈哈)所說js是C語言和Self語言一晚上情的產物, 他的生命力與發展遠遠超出做者的預期, 間接致使設計之初並無過多的考慮對數據結構的支持,
但es規範制定者彷佛已經察覺到了這一點, 因而最es6標準增長了set集合和map集合,有興趣的能夠查閱最新的es標準,這裏推薦阮一峯的es6入門 筆者認爲是一部不錯的教材(^_^筆者可不是作廣告),有興趣的能夠查閱,下面給出鏈接

es6 阮一峯http://es6.ruanyifeng.comjavascript


二維數組

Array.matrix = function(numrows, numcols, initial) {
      let arr = [];
      for (let i = 0; i < numrows; ++i) {
        let columns = [];
        for (let j = 0; j < numcols; ++j) {
          columns[j] = initial;
        }
        arr[i] = columns;
      }
      return arr;
    }

let Stack = (function(){
      function Stack() {
        this.dataStore = [];
        this.top = 0;
      }
      Stack.prototype.push = function(element) {
        this.dataStore[this.top++] = element;
      }
      Stack.prototype.peek = function() {
        return this.dataStore[this.top-1];
      }
      Stack.prototype.pop = function() {
        return this.dataStore[--this.top];
      }
      Stack.prototype.clear = function() {
        this.top = 0;
      }
      Stack.prototype.length = function() {
        return this.top;
      }
      return Stack;
    })();

隊列

let Queue = (function () {
      function Queue() {
        this.dataStore = [];
      }
      Queue.prototype.enqueue = function(element) {
        this.dataStore.push(element);
      }
      Queue.prototype.dequeue = function() {
        return this.dataStore.shift();
      }
      Queue.prototype.front = function() {
        return this.dataStore[0];
      }
      Queue.prototype.back = function() {
        return this.dataStore[this.dataStore.length-1];
      }
      Queue.prototype.toString = function() {
        var retStr = "";
        for (var i = 0; i < this.dataStore.length; ++i) {
          retStr += this.dataStore[i] + "\n";
        }
        return retStr;
      }
      Queue.prototype.empty = function() {
        if (this.dataStore.length == 0) {
          return true;
        } else {
          return false;
        }
      }
      return Queue;
    })()

優先隊列

let PriQueue = (function() {
      function Ele(value, code) {
        this.value = value;
        this.code = code;
      }
      function PriQueue() {
        this.dataStore = [];
      }
      PriQueue.prototype.enqueue = function(element) {
        this.dataStore.push(element);
      }
      PriQueue.prototype.dequeue = function() {
        var priority = this.dataStore[0].code;
        for (var i = 1; i < this.dataStore.length; ++i) {
          if (this.dataStore[i].code < priority) {
            priority = i;
          }
        }
        return this.dataStore.splice(priority,1);
      }
      PriQueue.prototype.front = function() {
        return this.dataStore[0];
      }
      PriQueue.prototype.back = function() {
        return this.dataStore[this.dataStore.length-1];
      }
      PriQueue.prototype.toString = function() {
        var retStr = "";
        for (var i = 0; i < this.dataStore.length; ++i) {
          retStr += this.dataStore[i].name + " code: " + this.dataStore[i].code + "\n";
        }
        return retStr;
      }
      PriQueue.prototype.empty = function() {
        if (this.dataStore.length == 0) {
          return true;
        } else {
          return false;
        }
      }
      return PriQueue;
    })()

單向鏈表

let LList = (function() {
      function Node(element) {
        this.element = element;
        this.next = null;
      }
    
      function LList() {
        this.head = new Node("head");
        this.foot = new Node("foot");
        this.head.next = this.foot;
      }
      LList.prototype.remove = function(item) {
        var prevNode = this.findPrevious(item);
        if (!(prevNode.next == null)) {
          prevNode.next = prevNode.next.next;
        }
      }
      LList.prototype.findPrevious = function(item) {
        var currNode = this.head;
        while ((currNode.next !== null) && (currNode.next.element != item)) {
          currNode = currNode.next;
          if (currNode.next === null) {
            currNode =null;
            break;
          }
        }
        return currNode;
      }
      LList.prototype.display = function() {
        var currNode = this.head;
        console.log(currNode.element);
        while (!(currNode.next == null)) {
          currNode = currNode.next;
          console.log(currNode.element);
        }
      }
      LList.prototype.find = function(item) {
        var currNode = this.head;
        while (currNode.element != item) {
          currNode = currNode.next;
          if (currNode === null) {
            break;
          }
        }
        return currNode;
      }
      LList.prototype.insert = function(newElement, item) {
        var newNode = new Node(newElement);
        var current = this.find(item);
        newNode.next = current.next;
        current.next = newNode;
      }
      return LList;
    })()

雙向鏈表

let DLList = (function () {
      function Node(element) {
        this.element = element;
        this.next = null;
        this.previous = null;
      }
      function DLList() {
        this.head = new Node("head");
        this.foot = new Node("foot");
        this.head.next = this.foot;
        this.foot.previous = this.head;
      }
      DLList.prototype.find = function(item) {
        var currNode = this.head;
        while (currNode.element != item) {
          currNode = currNode.next;
          if (currNode === null) {
            break;
          }
        }
        return currNode;
      }
      DLList.prototype.insert = function(newElement, item) {
        var newNode = new Node(newElement);
        var current = this.find(item);
        newNode.next = current.next;
        newNode.previous = current;
        current.next.previous = newNode;
        current.next = newNode;
      }
      DLList.prototype.remove = function(item) {
        var currNode = this.find(item);
        if (!(currNode.next == null)) {
          currNode.previous.next = currNode.next;
          currNode.next.previous = currNode.previous;
          currNode.next = null;
          currNode.previous = null;
        }
      }
      DLList.prototype.display = function() {
        var currNode = this.head;
        console.log(currNode.element);
        while (currNode.next !== null) {
          currNode = currNode.next;
          console.log(currNode.element);
        }
      }
      return DLList;
    })()

let BST = (function () {
      let Node = (function () {
        function Node(data, left, right) {
          this.data = data;
          this.left = left;
          this.right = right;
        }
        Node.prototype.show = function () {
          return this.data;
        }
        return Node;
      })()
    
      function BST() {
        this.root = null;
      }
      BST.prototype.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;
              }
            }
          }
        }
      }
      BST.prototype.inOrder = function(node) {
        if (!(node === null)) {
          this.inOrder(node.left);
          console.log(node.show() + " ");
          this.inOrder(node.right);
        }
      }
      BST.prototype.preOrder = function(node) {
        if (!(node === null)) {
          console.log(node.show() + " ");
          this.preOrder(node.left);
          this.preOrder(node.right);
        }
      }
      BST.prototype.postOrder = function(node) {
        if (!(node === null)) {
          this.postOrder(node.left);
          this.postOrder(node.right);
          console.log(node.show() + " ");
        }
      }
      BST.prototype.getMin = function() {
        var current = this.root;
        while (!(current.left == null)) {
          current = current.left;
        }
        return current.data;
      }
      BST.prototype.getMax = function() {
        var current = this.root;
        while (!(current.right == null)) {
          current = current.right;
        }
        return current.data;
      }
      BST.prototype.find = function(data) {
        var current = this.root;
        while (current != null) {
          if (current.data == data) {
            return current;
          }
          else if (data < current.data) {
            current = current.left;
          }
          else {
            current = current.right;
          }
        }
        return null;
      }
      BST.prototype.remove = function(data) {
        root = this.removeNode(this.root, data);
      }
      BST.prototype.removeNode = function(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 = this.getSmallest(node.right);
          node.data = tempNode.data;
          node.right = this.removeNode(node.right, tempNode.data);
          return node;
        }
        else if (data < node.data) {
          node.left = this.removeNode(node.left, data);
          return node;
        }
        else {
          node.right = this.removeNode(node.right, data);
          return node;
        }
      }
      BST.prototype.getSmallest = function(node) {
        if (node.left == null) {
          return node;
        } else {
          return this.getSmallest(node.left);
        }
     }
    
      return BST;
    })()

let Graph = (function() {
      function Graph(v) {
        this.vertices = v;
        this.vertexList = [];
        this.edges = 0;
        this.adj = [];
        for (var i = 0; i < this.vertices; ++i) {
          this.adj[i] = [];
          //  this.adj[i].push("");
        }
        this.marked = [];
        for (var i = 0; i < this.vertices; ++i) {
          this.marked[i] = false;
        }
        this.edgeTo = [];
      }
      Graph.prototype.addEdge = function (v, w) {
        this.adj[v].push(w);
        this.adj[w].push(v);
        this.edges++;
      }
      Graph.prototype.showGraph = function() {
        for (var i = 0; i < this.vertices; ++i) {
          let st = i + " -> " ;
          for (var j = 0; j < this.vertices; ++j ) {
            if (this.adj[i][j] != undefined) {
              st += this.adj[i][j] + ' ';
            }
          }
          console.log(st);
        }
      }
      Graph.prototype.dfs = function(v) {
        this.marked[v] = true;
        if (this.adj[v] != undefined) { 
          console.log("Visited vertex: " + v);
        }
        for (const w of this.adj[v]) {
          if (!this.marked[w]) {
            this.dfs(w);
          }
        }
      }
      Graph.prototype.bfs = function(s) {
        var queue = [];
        this.marked[s] = true;
        queue.push(s); // 添加到隊尾
        while (queue.length > 0) {
          var v = queue.shift(); // 從隊首移除
          if (v !== undefined) {
            console.log("Visisted vertex: " + v);
          }
          for (var w of this.adj[v]) {
            if (!this.marked[w]) {
              this.edgeTo[w] = v;
              this.marked[w] = true;
              queue.push(w);
            }
          }
        }
        console.log(this.edgeTo);
      }
      Graph.prototype.hasPathTo = function(s, v) {
        this.bfs(s)
        return this.marked[v];
      }
      Graph.prototype.pathTo = function(s, v) {
        var source = s;
        if (!this.hasPathTo(s, v)) {
          return undefined;
        }
        var path = [];
        for (var i = v; i != source; i = this.edgeTo[i]) {
          path.unshift(i);
        }
        path.unshift(source);
        return path;
      }
      Graph.prototype.topSort = function() {
        var stack = [];
        var visited = [];
        for (var i = 0; i < this.vertices; i++) {
          visited[i] = false;
        }
        for (var i = 0; i < this.vertices; i++) {
          if (visited[i] == false) {
            this.topSortHelper(i, visited, stack);
          }
        }
        for (var i = 0; i < stack.length; i++) {
          if (stack[i] != undefined && stack[i] != false) {
            console.log(this.vertexList[stack[i]]);
          } 
        }
      }
      Graph.prototype.topSortHelper = function(v, visited, stack) {
        visited[v] = true; 
        for (var w in this.adj[v]) {
          if (!visited[w]) {
            this.topSortHelper(visited[w], visited, stack);
          }
        }
        stack.push(v);
      }
      return Graph;
    })()
相關文章
相關標籤/搜索