實現優化雙向List,biList 的歷程

2021-08-27 14:00:26 字數 2910 閱讀 5319

緣由:聊天系統中,請求歷史記錄,要把資料插在前面,新來的訊息要插在後面,每一條又要按照索引取值。

經常看到 list.insert(0,x),這種**,真的很煩。。因為每次insert都要去複製陣列。就在想既然需要頻繁在前面插入資料,為什麼不用鍊錶呢,然後發現還有需求是要按索引取值,鍊錶的取值。。只能去不斷的next(),也是煩的一筆。於是,ovoniclist 應運而生!

思路就是  bilist 在需要改變容量的時候,容量變成當前size的3倍,然後把原有的資料放到中間,再去操作。這樣,首尾新增的時候,只有當需要擴容的時候(而不是list那樣每次)才會複製陣列,效率高一點

大概的示意圖如上。

需要的字段有,頭部,尾部,數量,陣列,容量

基本介面,頭部新增,尾部新增,按索引取值,按索引移除,迭代器 等等

private int _head;

private int _tail;

private int _size;

private t _items;

private int _capacity;

public void addfirst(t t)

public void addlast(t t)

public t this[int index]

public void removeat(int index)

public void clear()

public bool remove(t t)

public ienumeratorgetenumerator()

先看看需要改變容量的場景

1.往前面新增的時候頭部index到了0    _head == 0

2.往後面新增的時候尾部index到了陣列最後乙個    _tail == items.length-1

3.移除項的時候,容量過大,暫定    _size < _items.length / 4

然後碼**。做效能測試。

第一行耗時 是自己寫的ovoniclist ,第二行是linkedlist ,第三行是list

圖一:三種擴容條件放在乙個if裡面做判斷。  100w次測試,發現效率居然還比不上list.insert

納尼!!!??一定是我寫的有問題,於是把三種條件拆分了一下

圖二:拆分後,比list稍微快那麼一丟丟

還是不應該啊,繼續找原因,原來是最開始寫的 預設容量3,並且第乙個元素插入index為1,並沒有真正的插入到中間位置,於是優化了一下初始容量最小為11,並且插入位置 (_capacity - 1) / 2;

圖三:這下效能完爆list了,只比鍊錶慢一丟丟

還是不服,又對移除做了下優化,list中按index移除,直接就是從該index'開始從新複製後面的陣列去,稍微做了下優化,我判斷,如果是在前半部分,就陣列往後順序移動,如果在後半部分,就往前順序移動,果然又快了一丟丟

圖四:中間插入移除的時候,改變複製陣列為陣列順序移動,效能再好一點

最後這個結果已經算是比較滿意了,滿足了快速的雙端新增,按索引取值,非常適合聊天系統這種場景。接下來只需要新增一些 addrange、建構函式傳入陣列之類的了。不過這些,基本很少會用到。最後貼上全部**

using system;

using system.collections;

using system.collections.generic;

public class bilist: ireadonlylist

public bilist(int capacity)

public void addfirst(t t)

if (_head == 0)

_items[--_head] = t;

_size++;

}public void addlast(t t)

if (_tail == _items.length - 1)

_items[++_tail] = t;

_size++;

}public void clear()

public void removeat(int index)

//method 2

if (index <= (_size - 1) / 2)

_items[_head++] = default(t);

_size--;

}else

_items[_tail--] = default(t);

_size--;

}if (_size < _items.length / 4)

}public bool remove(t t)

}return false;

}private void prepare()

private void indexcheck(int index)

}public ienumeratorgetenumerator()

}ienumerator ienumerable.getenumerator()

public int count

}public t this[int index]}}

實現雙向繫結

ng和vue都有雙向資料繫結。vue是資料劫持,ng是藏之檢測 一 vue雙向資料繫結 訪問器屬性是物件中的一種特殊屬性,它不能直接在物件中設定,而必須通過 defineproperty 方法單獨定義。此例實現的效果是 隨文字框輸入文字的變化,span 中會同步顯示相同的文字內容 在js或控制台顯式...

雙向鍊錶實現

template class link link link pre null,link ne null void operator new size t void operator delete void ptr template link link freelist null template v...

PHP實現雙向佇列

作為開發人員,經常會在專案中遇使用到佇列,而有時候需要自己單獨實現佇列機制,而也有部分新手對與佇列認識不清晰,本教程,從 上,直觀的展示了佇列的實現 和使用過程。function 雙向佇列實現 author yg w date 2017 12 23 classqueue return self in...