名前:津田伸秀
サイト: http://vivi.dyndns.org/ twitter:vivisuke
facebook:https://www.facebook.com/nobuhide.tsuda
ぼちぼちソフト作家、年齢不詳のおじさん、自宅研究員(主席)
趣味:テニス、オセロ、思考ゲーム・パズル類
Qt/C++ 使い, 一応webアプリ(PHP, JS, jQ, SQL)も出来るよ
Windows用テキストエディタ ViVi を延々開発中
最近は、世界最速「さくさくエディタ」 開発中だよ
迷走中、お仕事募集中でござるぞ
ランダムアクセス | 挿入・削除 | |
vector | O(1) | O(N) |
list | O(N) | O(1) |
2分木 | O(Log N) | O(Log N) |
許されるのは O(N*Log N)まで
list<string> で行管理
list<string>::const_iterator View::line_iterator(int ln)
{
auto itr = lineMgr.cbegin();
for(int i = 0; i < ln; ++i) ++itr; // ここが O(L)
return itr;
}
void View::画面表示()
{
int ln = vScrollBar->value();
auto itr = line_iterator(ln);
while( 画面内の場合 ) {
*itr を表示;
++itr;
}
}
int ln = vScrollBar->value();
while( 画面内の場合 ) {
auto itr = line_iterator(ln);
*itr を表示;
++ln;
}
list<string>::const_iterator View::line_iterator(int ln)
{
if( ln が記憶行番行と同じ ) return 記憶イテレータ;
if( ln が記憶行番行より大きい ) {
if( ln が末尾から遠い )
記憶行、イテレータより探す;
else
末尾から探す;
} else {
if( ln が先頭から遠い )
記憶行、イテレータより探す;
else
先頭から探す;
}
itr, ln を記憶;
return itr;
}
template <typename T> class GapBuffer {
T *m_data; // データ領域
int m_gapIndex; // ギャップ位置
int m_gapSize; // ギャップサイズ
int m_size; // データサイズ、capacity = size + gapSize };
T GapBuffer::charAt(int pos) const
{
if( pos >= m_gapIndex ) // pos がギャップ以降
pos += m_gapSize; // ギャップサイズ分補正
return m_data[pos];
}
void GapBuffer::moveGapTo(int pos)
{
if( pos < m_gapIndex ) {
[pos, m_gapIndex) を [pos+m_gapSize, m_gapIndex+m_gapSize] に移動 m_gapIndex = pos; } else if( pos > m_gapIndex ) { [m_gapIndex+m_gapSize, pos+m_gapSize) を [m_gapIndex, pos) に移動 m_gapIndex = pos; }}
void GapBuffer:erase(int pos)
{
moveGapTo(pos); // ギャップを pos に移動
++m_gapSize; // ギャップサイズを増やすだけで文字が消える
}
void GapBuffer::insert(int pos, T ch)
{
if( ギャップが無い ) データエリアを(1.5~2倍に)拡張;
moveGapTo(pos); // ギャップを pos に移動
m_data[m_gapIndex++] = ch; // ギャップ先頭に文字挿入
--m_gapSize;
}
int lineStartPosition(int ln)
{
if( ln > m_stepIndex )
ln += m_stepSize;
return m_lv[ln];
}
void update(size_t ln, diffptr_t d)
{
if( !m_stepSize ) { // 差分が 0 の場合
m_stepIndex = ln;
} else if( ln < m_stepIndex ) { // ステップ行以前を編集した場合
while( m_stepIndex > ln ) {
m_lv[m_stepIndex--] -= m_stepSize;
}
} else if( ln > m_stepIndex ) { // ステップ行以降を編集した場合
do {
m_lv[++m_stepIndex] += m_stepSize;
} while( ln > m_stepIndex );
}
m_stepSize += d;
}