リスト構造

ハッシュテーブルを作る際に、ハッシュ値が被った時の処理を考えると、
自由に要素を追加可能なデータ構造が欲しくなるよね

こんなかんじの
list[0]:〇→〇
list[1]:〇→〇→〇
list[2]:〇
list[3]:〇→〇
list[4]:〇→〇→〇
list[5]:〇
list[6]:〇→〇
list[7]:〇

そうだ、そんなときはリスト構造を使おう!
リスト構造は、データをアドレスでつないだ構造をしています。
一番オーソドックスなリスト構造(単方向リスト)
h:head
t:tail
 [ h ]→ [ 1 ]→ [ 3 ]→ [ 5 ]→ [ 7 ]→ [ t ]

データ単体は以下のような形になります。

 118       アドレス  
[ 9 ]→NULL      [ データ値]→NULL
               ↑Next(次のデータのアドレス、初期値はNULL)

リスト型のデータを1個だけ作ると、どこかのアドレスにこんな感じのデータが1個作られます。

 アドレス  
[ データ値]→NULL
      ↑Next(次のデータのアドレス、初期値はNULL)

たとえば、アドレス0x022にデータが作られて、データ値を3で初期化して使おうとすると以下のようになります。

値は
 022  
[ 3 ]→NULL
      ↑Next(次のデータのアドレス、初期値はNULL)

ここから書きかけ

 head:ヘッド(データがここからつなっていく、「はじめ」を表すデータのアドレス)
  tail:テール(データの終わりを表すでーたのアドレス)
 データ: アドレス部 データ部 ネクス部 でできているよ
  アドレス部:データ自身のアドレス
   データ部:格納したい値
  ネクスト部:次のデータのアドレス

 整数 [ 1,3,5,7 ] がリストになっているイメージ
 h→1→3→5→7→t
  アクセス法
 ①headのデータアドレスを取得
  ②headのnextを見る(最初のデータにアクセスできる)
 ③nextのデータのnextを見る(次のデータにアクセスできる)
 ④ …
 ⑤nextがtailになったらそれ以上データはないよ
 
 今見ているアドレスを変数にしてたどっていく
   031     013     A15     FF2     109     BAD   アドレス(16進)
 [ h ]→ [ 1 ]→ [ 3 ]→ [ 5 ]→ [ 7 ]→ [ t ]
       013     A15     FF2     109     BAD
          ↑iterator
 Crr = head
  if(Crr.next != tail)
         Crr = Crr.next
	 if(crr.data == 5)5の時の処理
データの追加
   031     013     A15     FF2     109     BAD   アドレス(16進)
 [ h ]→ [ 1 ]→ [ 3 ]→ [ 5 ]→ [ 7 ]→ [ t ]
       013     A15     FF2     109     BAD

 headとtailのアドレスは知っているとき、
 リスト構造のデータを用意 整数データ 9 を追加 
  118
 [ 9 ]→NULL (NULLはどこにもつながっていないよというアドレス(数値でいう0))
 nextがtailになっているデータにつなぐ!
  if(Crr.next == tail)
     Crr.next = 118   (Crr:109 Crr.next:118)
     Crr = Crr.next   (Crr:118 Crr.next:NULL)
     Crr.next = tail  (Crr:118 Crr.next:tail)

リスト構造の種類

呼ばれ方
ネットを見るといろいろ表記ゆれがありますが、基本的に以下のものは同じリスト構造を指します。

リスト構造の種類

配列VSリスト

配列とリストの違い

イテレータを使って、nextのデータにアクセスしていくソースコード

#include <iostream>
#include <list>
using std::cout;
using std::cin;
using std::endl;
using std::list;

//STLのlistを使うよっていうinclude
//テンプレート(いろんな方に対応できる便利な奴)



int main() {
	//intのリストを作りたいな
	list<int> ilist;
	//floatのリストを作りたいな
	//list<float> flist;

	int indata;
	do{
		cout << "整数を入力:";
		cin >> indata;
		if(indata != -1)
			ilist.push_back(indata);
		else
			break;
	}while(true);
	
	list<int>::iterator theI = ilist.begin();
	cout << *theI << endl;  //*theI theIのアドレスの中身のデータを取り出す
	theI = std::next(theI); //theI++
	cout << *theI << endl;
	//cout << ilist[2] << endl; ランダムアクセスはできん!
}