數據驅動型的設計02

  • 2019 年 10 月 8 日
  • 筆記

本系列從數據結構相關的計算機知識出發,從數據的角度提出一些數據驅動的設計思維模式。

第01期總體介紹數據結構與設計的關係,用數據結構的方式來思考設計,並通過幾個案例介紹一些大的思路。

第02期介紹數據結構中的鏈表結構,並探討設計中可能的鏈表數據。

1 何為鏈表?

1.1 概念

一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接實現的。圖示:

來個形象點的圖:

1.2 鏈表有特點呢?

查找某個元素:需要從鏈表中第一個元素開始,一直找到目標元素的位置。

插入/刪除某個元素:只要修改元素中的指針。

2 用代碼實現一個鏈表結構

採用Javascript來實現一個鏈表結構,加深對鏈表的理解,Chrome瀏覽器打開console面板,先實現一個鏈表的節點。

2.1 節點

此節點保存了數據本身(value的值)及下一個節點的位置(下一個節點),輸入:

class LinkedListNode {   constructor(value,next) {      this.value = value;      this.next = next;   }  }

這裡我們需要了解下ES6的class特性,下文的例子定義了一個「類」——Point,可以看到裏面有一個constructor方法,這就是構造方法,主要寫一些Point對象的屬性,例如x和y的坐標值;而傳統的方法是通過構造函數,定義並生成新對象,然後通過 prototype 屬性向對象添加屬性和方法。

class Point {   constructor(){      this.x=0;      this.y=0;    // ...   }   toString(){    // ...   }   toValue(){    // ...   }  };        // 等同於    function Point(){      this.x=0;      this.y=0;      //...  };    Point.prototype = {   toString(){},   toValue(){}  };

2.2 鏈表的基本結構

主要是有兩個屬性,head記錄的是最開始的節點,tail記錄的是結尾的節點。其中由於每個節點都有一個next屬性指向下一個節點,所以head記錄了整條鏈表的節點。

class LinkedList{    constructor(){            this.head = null;           this.tail = null;      }}

初始化一個鏈表結構:

var ls=new LinkedList();

2.3 添加方法

下面為鏈表結構的數據添加:增刪改查的方法。

添加節點的方法:

append – 在結尾插入節點

prepend – 在開始插入節點

查詢節點的方法:

find

刪除節點的方法:

delete

2.3.1 prepend方法

添加prepend方法,圖示結合代碼:

LinkedList.prototype.prepend=function(value) {      const newNode = new LinkedListNode(value,this.head);      // 往head添加節點   this.head = newNode;      // 如果tail為空,往tail添加此節點        if (!this.tail) {           this.tail = newNode;     }        return this;  }

實驗下prepend方法:

ls.prepend(0);console.log(JSON.stringify(ls,null,2));

打印出來:

{  "head": {         "value": 0,         "next": null   },     "tail": {         "value": 0,         "next": null   }  }

繼續添加:

ls.prepend(1);  console.log(JSON.stringify(ls,null,2));

結果:

"{   "head": {     "value": 1,     "next": {       "value": 0,       "next": null     }   },   "tail": {     "value": 0,     "next": null   }  }"

經過多次實驗,會發現,head是個一層層嵌套的結構,通過head可以找到任何一個節點(按順序),而tail永遠是存儲的最後一個節點。

2.3.2 append方法

為鏈表結構添加append方法:

LinkedList.prototype.append=function(value) {      const newNode = new LinkedListNode(value);    // 如果head為空,則head設為newNode   if (!this.head) {          this.head = newNode;          this.tail = newNode;          return this;     }       // 把新的newNode設為tail     this.tail.next = newNode;      this.tail = newNode;      return this;   }

實驗下append方法:

ls.append(10);  console.log(JSON.stringify(ls,null,2));

2.3.3 compare方法

為了實現刪除delete,我們得先實現比對兩個數值是否相等的功能,相等的話返回0:

LinkedList.prototype.compare=function(a,b){        if (a === b) {          return 0;     }        return a < b ? -1 : 1;};

2.3.4 delete方法

根據value值來刪除節點,凡是等於目標value的節點都被刪除:

LinkedList.prototype.delete=function(value) {      let deletedNode = null;      // head節點是否需要被刪除   while (this.head && this.compare(this.head.value, value)===0) {       deletedNode = this.head;        this.head = this.head.next;     }          let currentNode = this.head;        if (currentNode !== null) {        // 遍歷每一個節點       while (currentNode.next) {        if (this.compare(currentNode.next.value, value)===0) {           deletedNode = currentNode.next;           currentNode.next = currentNode.next.next;         } else {           currentNode = currentNode.next;         }       }     }       // 判斷tail節點是否需要刪除     if (this.compare(this.tail.value, value)===0) {            this.tail = currentNode;     }        return deletedNode;     };

2.3.5 find方法

實現一個簡單的查找方法,找到一個值等於value的節點,並返回,代碼如下:

LinkedList.prototype.find=function(value) {      let currentNode = this.head;        while (currentNode) {        if (value && this.compare(currentNode.value, value)===0) {          return currentNode;       }     currentNode = currentNode.next;     }        return null; }

2.3.6 toArray方法

鏈表結構的數據轉化為數組數據:

  LinkedList.prototype.toArray=function() {        const nodes = [];        let currentNode = this.head;        while (currentNode) {           nodes.push(currentNode);           currentNode = currentNode.next;         }        return nodes;   }

至此,我們對鏈表結構的數據應該已經理解得比較深刻了。接下來,我們探討下在設計中,有哪些是可以被鏈表結構的數據所表示的?

讚賞的方式可以是點廣告~

3 設計中的鏈表結構

思考下設計里,哪些元素/手法是可以被鏈表結構的數據表示的?我們先了解下鏈表結構的幾種基本類型。

3.1 鏈表結構的幾種基本類型

Singly linked list 這是最簡單的鏈表結構:

Double Linked List 雙向鏈表的結構:

Circular linked list循環鏈表的結構:

3.2 設計中的鏈表結構

鏈表本身的特點是一個節點連接着下一個節點,非常適合描述流程性,有前後關係的數據。

1)用戶體驗的流線

室內設計中,不同空間游線之間的關係;

展覽館的游線設計;

UX設計中頁面的跳轉流線;

2)設計思路的解構

景觀設計中,一層層的關係,地面鋪裝,樹池花台,喬木灌木,亭廊構架;

平面設計中,背景,主體內容,配色,布局,構圖等;

更多跟設計的結合,歡迎留言補充。

參考資料:

https://en.wikipedia.org/wiki/Linked_list