Datawhale | 編程第6期 Test 1

1. 用數組實現一個順序棧

棧: 當某個數據集只涉及在一端插入和刪除數據, 並且滿足後進先出, 就該使用棧這種數據結構

順序棧

function Stack() {
  this.dataStore = [];
  this.top = 0;
  this.push = push;
  this.pop = pop;
  this.peek = peek;
  this.length = length;
  this.clear = clear;

  function push(element) {
    return this.dataStore[this.top++] = element;
  }

  function pop() {
    if (this.top > 0) {
      return this.dataStore[--this.top];
    } else {
      return undefined;
    }
  }

  function peek() {
    return this.dataStore[this.top - 1];
  }

  function length() {
    return this.top;  
  }

  function clear() {
    delete this.dataStore;
    this.dataStore = [];
    this.top = 0;
  }
}

// Test
const stack = new Stack();

stack.push(1);
console.log(stack.length());
console.log(stack.pop());

2. 用鏈表實現一個鏈式棧

class Stack {
  constructor() {
    this.top = null;
    this.size = 0;
  }

  push(value) {
    ++this.size;
    const Node = new StackNode(value);

    if (this.top == null) {
      this.top = Node;
    } else {
      Node.next = this.top;
      this.top = Node;
    }
  }

  pop() {
    if (this.size <= 0) {
      return null;
    }

    --this.size;
    const PopedNode = this.top;
    this.top = this.top.next;

    return PopedNode.value;
  }

  empty() {
    while (this.top != null) {
      const currentNode = this.top;
      currentNode = null;
      --this.size;
      this.top = this.top.next;
    }
  }

}

class StackNode {
  constructor(data) {
    this.value = data;
    this.next = null;
  }
}

// Test
const stack = new Stack();
stack.push(1);
console.log(stack.size);

3. 編程模擬實現一個瀏覽器的前進、後退功能

class History {
  constructor() {
    this.length;
    this.st = Stack();
    this.vice_st = Stack();
  }

  go(url) {
    this.st.push(url);
  }

  forward(url) {
    this.st.push(url);
  }

  back() {
    const poped = this.st.pop();
    this.vice_st.push(poped);
  }

}

// 鏈式棧
class Stack {
  constructor() {
    this.top = null;
    this.size = 0;
  }

  push(value) {
    ++this.size;
    const Node = new StackNode(value);

    if (this.top == null) {
      this.top = Node;
    } else {
      Node.next = this.top;
      this.top = Node;
    }
  }

  pop() {
    if (this.size <= 0) {
      return null;
    }

    --this.size;
    const PopedNode = this.top;
    this.top = this.top.next;

    return PopedNode.value;
  }

  empty() {
    while (this.top != null) {
      const currentNode = this.top;
      currentNode = null;
      --this.size;
      this.top = this.top.next;
    }
  }

}

class StackNode {
  constructor(data) {
    this.value = data;
    this.next = null;
  }
}

隊列

1.用數組實現一個順序隊列

class Queue {

  constructor() {

    this.items = [];

  }

  /**

   * 向隊尾添加一個(或多個)新的元素

   * @param {*} element 新元素

   */

  enqueue(element) {

    this.items.push(element)

  }

  /**

   * 移除隊列的第一(即排在隊列最前面的)項,並返回被移除的元素

   */

  dequeue() {

    // 根據隊列的先進先出原則,使用shift方法

    // shift方法會從數組中移除存儲在索引爲0的元素

    return this.items.shift()

  }

  /**

   * 返回隊列中的第一個元素--最先被添加,也將是最先被移除的元素。

   * 隊列不做任何變動(不移除元素,只返回元素信息)

   */
  front() {

    return this.items[0]

  }



  /**

   * 清除隊列中的所有元素

   */

  clear() {

    this.items = []

  }


  /**

   * 如果隊列中不包含任何元素,返回true,否則返回false

   */

  isEmpty() {

    return this.items.length === 0

  }


  /**

   * 返回隊列包含的元素個數,與數組length屬性類似

   */

  size() {

    return this.items.length

  }


  /**

   * 隊列內容字符串化

   */

  toString() {

    return this.items.toString()

  }

}

2. 用鏈表實現一個鏈式隊列

//節點
function Node(data){
    this.data = data;
}
function Queue() {
    var node = new Node(null);
    this.front = node;
    this.rear = node;
}
//長度
Queue.prototype.length = function(){
    var length = 0;
    var node = this.front;
    while(node!=this.rear){
        node = node.next;
        length++;
    }
    return length;
}
Queue.prototype.enterQueue = function(node){
    node.next = null;
    this.rear.next = node;
    this.rear = node;
    return 0;
}
Queue.prototype.deleteQueue = function(){
    var p = this.front.next;
    if(this.rear == this.front){
        return 1;
    }
    this.front.next = p.next;
    if(this.rear == p){
        this.rear = this.front;
    }
    delete p;
}

3. 實現一個循環隊列

function Queue(maxSize) {
    this.data = new Array(maxSize);
    this.front = 0;//頭指針
    this.rear = 0;//尾指針
    this.maxSize = maxSize;
}
//長度
Queue.prototype.length = function(){
    return (this.rear-this.front+this.maxSize)%this.maxSize;
}
Queue.prototype.enterQueue = function(data){
    if((this.rear+1)%this.maxSize==this.front){
        //滿
        return 1;
    }
    this.data[this.rear] = data;
    this.rear = (this.rear+1)%this.maxSize;
    return 0;
}
Queue.prototype.deleteQueue = function(){
    if(this.front == this.rear){
        //空
        return 1;
    }
    this.front = (this.front+1)%this.maxSize;
    return 0;
}

鏈表

1. 實現單鏈表、循環鏈表、雙向鏈表,支持增刪操作

class Node {  // 鏈表節點
  constructor(element) {
    this.element = element;
    this.next = null;   // 節點的指向下個節點的指針
  }
}


class NodeList {   //  鏈表
  constructor(item) {
    this.head = new Node(item);   //  初始化鏈表的頭節點
  }
  /**
   * @description 插入元素
   * @param {需要插入的元素} newItem 
   * @param {插入到某一元素之後} beforeItem 
   */
  insertInNext(newItem, beforeItem) {
    let newNode = new Node(newItem);
    if (beforeItem) { //  判讀是否是插入到指定節點後面,如果不是則插入到最後一個節點。
      let currNode = this.find(beforeItem);
      newNode.next = currNode.next;
      currNode.next = newNode;
    } else {
      let lastNode = this.findLastNode();
      lastNode.next = newNode;
    }
  }
  /**
   * @description 刪除元素
   * @param {刪除的元素} newItem 
   */
  remove(item) {
    let preNode = this.findPreNode(item);  //  找到前一節點,將前一節點的next指向該節點的next
    if (preNode.next != null) {
      preNode.next = preNode.next.next;
    }
  }
  /**
   * @description 查找元素的節點
   * @param {查找的元素} item 
   */
  find(item) { //  根據元素查找節點
    let currNode = this.head;
    while (currNode.element !== item && currNode) {
      if (currNode.next) {
        currNode = currNode.next;
      } else {
        currNode = null;
      }
    }
    return currNode;
  }
  /**
   * @description 查找最後一個節點
   */
  findLastNode() {
    let currNode = this.head;
    while (currNode.next) {
      currNode = currNode.next;
    }
    return currNode;
  }
  /**
   * @description 查找元素的前一節點
   * @param {查找的元素} item 
   */
  findPreNode(item) {
    let currNode = this.head;
    while (currNode && currNode.next && currNode.next.element !== item) {
      if (currNode.next) {
        currNode = currNode.next;
      } else {
        currNode = null;
      }
    }
    return currNode;
  }
  toString() {
    let currNode = this.head;
    let strList = [];
    while (currNode.next) {
      strList.push(JSON.stringify(currNode.element));
      currNode = currNode.next;
    }
    strList.push(JSON.stringify(currNode.element));
    return strList.join('->')
  }
}

2. 實現單鏈表反轉

// 判斷對象是否爲空
function isEmptyObject(obj) {
  for (var name in obj) {
  return false;
}
  return true;
} 

function ReverseList(pHead) {
    if (isEmptyObject(pHead)) {
        return false;
    }
    var pre = null;
    var next = null;
    while (pHead != null) {
        next = pHead.next;
        pHead.next = pre;
        pre = pHead;
        pHead = next;
    }
    return pre;
}

3. 實現兩個有序的鏈表合併爲一個有序鏈表

var mergeTwoLists = function(l1, l2) {
  if (!l1) return l2;
  if (!l2) return l1;
  let head;
  if (l1.val <= l2.val) {
    head = l1;
    head.next = mergeTwoLists(l1.next, l2);
  } else {
    head = l2;
    head.next = mergeTwoLists(l1, l2.next);
  }
  return head
}

4. 實現求鏈表的中間結點


var middleNode = function(head) {
  var tail = mid = head;  //  尾部和中間結點指針
  var count = 0;
  while (tail.next !== null) {
    tail = tail.next;
    count ++;
    if (count === 2) {
      mid = mid.next;
      count = 0;
    }
  }
  if (count === 1) {
    mid = mid.next;
  }
  return mid;
}

參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章