SLList: 単方向リスト
3章は連結リスト,Nodeをどう繋ぐかみたいなお話.
一番最初はまずNodeを定義する.
Nodeは単純で値と繋がってる次のノードを持つようなものとなる.
単方向なので、次のノードのみを持つようにm_nextのみを持つわけだ.
class Node
{
public:
Node(T value)
: m_value(value)
, m_next()
{ }
public:
T m_value;
std::shared_ptr<Node> m_next;
};
Listが持つのはHeadとTailのNode.
後はsizeを保持しておく.
Sizeに関してはそのまま返せばOK.
追加に関しては簡単.
まずはノードを作ってuに格納.
その後、現状のheadをuのm_nextとして、headがuになるようにする.
T Push(T x)
{
std::shared_ptr<Node> u = std::make_shared<Node>(x);
// Pushは頭に繋げるため、head側からつける
u->m_next = m_head;
m_head = u;
// ...
}
特殊条件として、sizeが0のときはデータがない.
この時はtailに関してもuを設定しておく.
あとはSizeを+1しておけばOK.
削除は簡単.
PopはHead側から削除を行うため、headの値をuに保持して、headをu->m_nextにするだけ.
あとはuを解放して、sizeを下げるのみ.
ただし、sizeが0ならTailにもデータがある状態なので、こっちにも保持しているのを開放する.
std::shared_ptr<T>なので解放しないと残っちゃう.
// 削除
T Pop()
{
if (m_size == 0) { return T{}; }
T x = m_head->m_value;
// head側から削除なので、
// headをnextに付け替えておく
auto u = m_head;
m_head = u->m_next;
// 解放
u.reset();
// サイズが0の場合tailにも同じ値が入ってるので、
// ここも削除しておく
if (--m_size == 0)
{
m_tail.reset();
}
return x;
}
Removeに関しては全く同じため、Popを呼び出すのみにしてみた.
最後にAdd,PushはHeadから追加してたのに対して、AddはTailから追加する.
そこが違うだけなので、Tailのm_nextに登録して、Tailを更新するだけ.
// 追加
bool Add(T x)
{
std::shared_ptr<Node> u = std::make_shared<Node>(x);
if (m_size == 0)
{
// 初回のみHeadにも付ける
m_head = u;
}
else
{
// 今の最後尾の次にマーク
m_tail->m_next = u;
}
// 最後尾に追加
m_tail = u;
// Count Up
m_size++;
return true;
}
これで単純な単方向リストが完成した.