緣由:聊天系統中,請求歷史記錄,要把資料插在前面,新來的訊息要插在後面,每一條又要按照索引取值。
經常看到 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...