ツリー構造について

一般的な話

基礎用語

ディレクトリでも、XML でもツリー構造とその基本的な対処法を知らないことにはどうにもなりません。
基本的な対処法とは再帰的な処理のことです。リカーシブ処理とも言います。
基礎用語と表現法について簡単に述べます。
自分も専門家じゃないので、いい加減なところもあるとは思いますが、ツリー構造を扱うモジュールは これくらいのことを知らないと困るので作りました。
きちんと学びたい方は、しかるべき文献を読んだほうがいいかもしれません。
スキルのある方は、読み飛ばしてもらっても構いません。


木(tree)は、ノード(node)と葉(leaf)から成り立っていて、枝が出てないやつを葉(leaf) と言っていて、枝が出ているやつをノード(node)と言います。一番上にあるのを根(root)と 言います。
現在自分がいるところから見て上を親(mother,parent)、自分と同じ親で同じ階層のものを兄弟(sister,sibling)、 自分を親とするものを子(daughter,child)と言います。上の階層の全体を祖先(ancestors)と言うふうに呼びます。
兄弟は状況によってleft, rightで指定されたり複数形でまとめて参照されたりします。
子もたいていの場合複数形で指定されます。何番目の子と言う指定の場合もあるでしょう。

表現

上のような図の表現もツリー構造の表現の一つですがこの表現しかないわけではありません。
a
	b
		c
			1
			2
		d
			3
			e
				4
				5
				6
	7
こんなのでも表現の一つになります。インデントの深さで、階層を表しています。
(a,(b,(c,1,2),(d,3,(e,4,5,6))),7)
これも同じことを表してます。
(((1,2,c),(3,(4,5,6,e),d),b),7,a)
これも同じことです。
括弧表現と言われます。
ポーランド記法・逆ポーランド記法なんかを調べられると面白いと思います。
ここでa-eをhtmlのタグだと思ってみましょう。
<a><b><c>1,2</c><d>3<e>4,5,6</e></d></b>7</a>

整形すると
<a>
	<b>
		<c>1,2</c>
		<d>
			3
			<e>4,5,6</e>
		</d>
	</b>
	7
</a>
どうでしょうか。htmlとかXMLも一つの表現だということが分かりますね。
詳しいことは専門書で学んで下さい。

再帰

アップルスクリプトで再帰の例を一つ作ってみます。
まずハイパーカードで、フィールド一つとボタン一つを作って下さい。
フィールドの名前を出力として下さい
ボタンに以下のスクリプトをかきます。
on mouseUp
	set card field "出力" to ""
	set |リスト| to {"a", {"b", {"c", "1", "2"}, {"d", "3", {"e", "4", "5", "6"}}}, "7"}
	set |深さ| to 0
	|再帰する|(|リスト|, |深さ|)
end mouseUp

on |再帰する|(|引数|, |深さ|)
	if class of |引数| = list then
		set |インデント| to |インデントする|(|深さ|)
		set card field "出力" to card field "出力" & |インデント| & item 1 of |引数| & return
		set |引数| to rest of |引数|
		
		repeat with i from 1 to length of |引数|
			set |深さ| to |深さ| + 1
			|再帰する|(item i of |引数|, |深さ|)--(1)
			set |深さ| to |深さ| - 1
		end repeat
	else
		set |インデント| to |インデントする|(|深さ|)
		set card field "出力" to card field "出力" & |インデント| & |引数| & return
	end if
end |再帰する|

on |インデントする|(|深さ|)
	set |インデント| to ""
	repeat |深さ| times
		set |インデント| to |インデント| & tab
	end repeat
	return (|インデント|)
end |インデントする|
(1)で自分自身を呼び出してます。
括弧表現が、インデントの表現に変わってますね。
ツリー構造そのものは変化してません。表現を変えてるだけです。
このような変換をして、見やすさを追及していくと言うことです。
場合によってはツリー構造そのものを作り替える場合もあります。
その場合でも再帰はよく使われます。
再帰はメモリをたくさん必要とします。
アップルスクリプトではよくメモリが足りなくなるので、ここでは例としてあげましたが使わないことにします。
MacPerlではそんなことはまれなので、こういうことはMacPerlでやってもらう事にします。
再帰を使わなくても出来ますが、分かりにくくなります。再帰の解消は考えません。
一応作ったやつを置いておきます。 ダウンロード

アプリケーションで考えるツリー構造

FinderとT-TimeとActaとEasy Viewでそれぞれの表現について考察します。
どのようの表現をしたら見やすいかとか検索しやすいか、と言うのを考えるのは大切なことです。
表現は違うけれども、構造は同じだということも念頭にいれてみていきましょう。

Finder


ディレクトリでも一つの表現ですね。MacOSXでは、カラム表示と言うのが加わってますが、あれもそうです。
ファイルや、フォルダは、パスによる表現がされる事もありますが、同じフォルダに同じ名前のものが存在しないからこそ、 出来る表現なのです。

T-Time

縦書きで読めてルビもつくテキストビューワT-Timeには、アウトラインモードというのがあります。
○a
	○b
		○c
			1
			2
		○d
			3
			○e
				4
				5
				6
	7
このようなテキストの表現を解釈して下のように表示します。
次に述べるActaと似てますが、ページのスタイルでやっているので端の方のアウトラインは、無意味になってしまいます。
しかしテキストを解釈してくれるのは大きいと思います。
荒らされている掲示板を読むとき重宝します。
関係ありませんが、
pdfを読む機能もあって、読んだやつを保存するとテキストにしてくれます。
pdfをテキストにする方法をこれしか知らないので重宝してます。
LatexでコンパイルしてPostScriptから変換したpdfの数式とかは、だめみたいです。
画面の再描写が遅いので、古いのを使ったりしてます。

Acta

このような表現の元祖かもしれません。Actaのようなという表現は、今でも使われるかもしれません。
T-Timeもアウトラインモードの時は、スクロールの方がいいような気がします。
祖父、弟、子と言う表現は上でも出てきました。

Easy View

上に二段しかありませんが、MacOSXのカラム表示風のナビゲーションを持っていて、下に内容を表示しています。
setextという書式で解釈された文章を読んでくれます。use styleと言うのをチェックすると太字のようなスタイルを入れられます。
これを手本にしてhtmlとかPodとかを読めるような感じのものを作っていきたいと思います。