SimpleBoxes

solipo 0.07

solipo ver 0.07 を公開しています。→ [solipo 紹介ページ]

solipo は、Windows 上で動作する polipo の GUI ラッパーアプリケーションです。

「solipo」をダウンロード

solipo 0.07 では、ver 1.0.5 のプレリリースとして公開された polipo build 20080907 を適用しています。

古いバージョンの solipo からは、 solipo.exe と polipo.exe を差し替えることでバージョンアップできます。

これまでの関連記事

スポンサーリンク

V470 Cordless Laser Mouse を使っています

三ヶ月ほど前にワイヤレスマウスを購入しました。

[写真]V470 Cordless Laser Mouse

ご存知のように MacBook には USB ポートが二つしかありません。

私はマウスを常用するので、マウスによって USB ポートが一つ占有されると、実質的に USB ポートはひとつだけになってしまいます。

空いている USB ポートが「ひとつ」か「ふたつか」の違いは (特に心理的に) 大きくて、以前からワイヤレスマウスの購入を検討していました。

USB ポートを確保するという前提があるので、USB ポートに無線のレシーバーを差して利用するマウスは対象外になります。

無線 LAN や Apple Remote 用の赤外線ポートを利用したマウスというのは、とりあえず聞いたことがないので、必然的に Bluetooth マウスを検討することになります。

無線 LAN に関しては synergy などのマウス・キーボード共有ツールを利用するというのは考えられますが、趣旨とは離れるので除外。

購入まで

Bluetooth マウスは、案外選択肢がありません。

以前よりは増えたとは思うのですが、Bluetooth 以外のワイヤレスマウスと比べると、やはり少ない印象があります。

あってもちょっとデザインが好きになれそうにないものだったり……。

これまで利用していたマウスは、Logitech Optical Mouse USB というモデルです。Logitech (日本では、ロジクール) は色んなマウスを出していますが、ごく基本的な光学式マウスになると思います。

  • USB 接続
  • 光学式マウス
  • チルトホイール
  • 2 ボタン + ホイールボタン

軽くて大きさも手頃なので、安いモデルではありますが、使い勝手は十分です。

日本では、ロジクール Optical Mouse が一番近いモデルになるでしょうか。

機能的には、これと同等であれば十分です。つまり、

  • Bluetooth 対応
  • 光学式マウス
  • スクロールホイール (できれば水平方向も対応)
  • 2 ボタン以上

あたりが条件になります。MacBook は標準で Bluetooth に対応しているので、Bluetooth レシーバーは必要ありません。

購入候補

まず、真っ先に考えたのが、Wireless Mighty Mouse でした。

ワイヤレスではない、Mighty Mouse は所有していて、使い勝手自体はそれほど悪くないという印象を持っています。

Mighty Mouse からパワーアップしている点は、

  • Bluetooth 対応
  • レーザー式

という点でしょうか。Apple 純正ですから、MacBook との (特にソフトウェア面での) 相性もばっちりなはずです。

Mighty Mouse は、スクロールホイールにあたる「スクロールボール」が特徴的です。トラックボールの小さい奴がマウスについているような感じ。

スクロールボールは小さめですが、小技の効いたフィードバックのおかげで使い勝手は悪くありません。

ただし、このスクロールボールに「汚れが溜まりやすい」という大きな欠点があります。汚れが溜まると、この部分の反応が鈍くなり使い勝手が悪くなります。

この機構のおかげでメンテナンスがやや面倒な印象があります。

ぱっと見たところ、Wireless Mighty Mouse でも、この部分には特に改善がない様子で、アップルストアのレビューでも同様な意見が散見されます。今回の対象からは外れました。

Microsoft Wireless Notebook Presenter Mouse 8000 というプレゼン用のリモートコントローラーとしても利用できる多機能マウスもありますが、こちらは高め。

V470 Cordless Laser Mouse

今回購入したのは、V470 Cordless Laser Mouse for Notebooks (以下、V470) というマウスです。

[写真]V470 パッケージ

このマウスは 2007 年 8 月頃に発表されていますが、発表当初からやや気になっていました。

ニュージーランドでの定価は $99.90 で、家電量販店では $79 (特売時に $65 から $69) ぐらいです。この価格だと個人的にはちょっと高いかなという感じです。

ところが、先日たまたま覗いた PC ショップで、$59 という価格 (2008.10.20 現在のレートで換算すると、日本円で 4,000 円弱) で売られているのを発見して、確保と相成りました。

V470 は、機能的にはごく一般のレーザーマウスになるかと思います。

  • Bluetooth 対応
  • レーザー式
  • チルトホイール
  • 2 ボタン + ホイールボタン

「for Notebooks」とある通り、大きさは小振りです。PlayStation のコントローラーの握り部分からボタン部にかけてぐらいの大きさでしょうか。私はそれほど手が大きくありませんが、すっぽりと覆える感じです。

ただし、内部に単三乾電池を二本入れるため、Logitech Optical Mouse USB より重くなっています。

レーザー式マウスは初めて利用します。レーザー式ではない光学式マウスと違って、一見では LED (発光ダイオード) が光っているように見えないんですね。

Bluetooth 対応のせいか、光学形式の違いのせいかは分からないのですが、最初、マウスカーソルの移動速度に対して違和感を感じました。

移動速度はやや速めなんですが、なんかちょっと飛ぶような感じ。サンプリングレートが低いような印象って言ったら伝わるでしょうか。

もっともここら辺は、「システム環境設定」で調節できますし、すぐに馴れると思いますので、大きなマイナスポイントにはならないでしょう。

パッケージには、付属アプリケーション (「Logitech (Logicool) Control Center」など) のインストールディスクやら巾着袋などが付いてきます。

[写真]V470 パッケージ内容

Mac OS X では、標準のドライバで Bluetooth マウスとして認識されますから、付属のソフトウェアはインストールしなくても、マウスはそのままで利用できます。

付属ソフトをインストールすると、V470 の電池残量やマウスボタンやホイールのカスタマイズができるようになります。

[画像]Device Manager for V470

V470 自体は日本では未発売ですが、付属ソフトウェアは上記画像の通り、日本語化されています。

[画像]Battery Status of V470

使い始めて三ヶ月、ほぼ毎日 2,3 時間程度の利用するという状況ですが、バッテリーはまだ「十分」と表示されています。

利用しないとき (MacBook をスリープさせる時) は、その都度、マウス底面の電源をオフにしています。

比較 Mighty Mouse vs. V470

手元にあるワイヤードな Mighty Mouse と V470 とを比較してみました。

[写真]Mighty Mouse と V470

 Mighty MouseV470 Cordless
110 mm100 mm
60 mm58 mm
高さ30 mm36 mm
重さ79 g110 g

[写真]重さ比較 (Mighty Mouse vs. V470)

V470 の重さは、単三電池 2 本を含んでいます。Mighty Mouse の方はコードの重さをほぼ含んでいません。

Mighty Mouse の方が平べったい感じで、V470 は小さくやや厚みがあります。この「厚み」のおかげで「すっぽりと覆うように」持つ感じがあります。

安物マウスを何個も買って冒険するよりも、しっぽ無しマイティマウスを買った方がいいのかもしれない。近くに Apple ストアがあればいいのに><

新しい○○が来た - p15.jp

すでにコメントもしているのですが、個人的には Mighty Mouse よりもこちらの V470 を強くお勧めします。この記事が参考になれば、幸いです。

スポンサーリンク

新しい MacBook が発表された

ご承知の通り、新しい MacBook が発表されました。

[画像]MacBook (2008) © 2008 Apple Inc.

第一印象は「かなりいい感じ」。

気になるのは、新しいぱっと見ボタンレスなトラックパッドでしょうか。実物に触れて来たという t0mori さん、

トラックパッドは思いの外普通に、今までとまったく同じ感覚で操作出来、拍子抜けだったくらい。一瞬ボタンがないのを忘れてクリックしている僕がいました。

t0moriBlog :: MacBookに触ってきた。

見た目よりも「普通」とのこと。やはり製品として形としている以上、完成度は高い様子。

今まで通り2フィンガータップでのコンテキストメニュー表示も選択出来、左右に物理ボタンで割り当てる事も出来る。マルチタッチジェスチャーも快適で、確かにこれは新しいUIの到来を予感させる仕上がり。独立したボタンを排しパッド面積を稼ぎつつ、物理的なボタンを残したアップルらしいアプローチには感服。

t0moriBlog :: MacBookに触ってきた。

……なるほど。でも、個人的に気になっている部分は「そこ」じゃないんですよね。

個人的に新しいトラックパッドで気になっているのは、ドラッグ & ドロップの操作です。

マウスで説明すると「移動距離が足りず、一度宙に浮かせてから移動する」という操作を、この新しいトラックパッドでどのように解決しているのか、がすごく気になっています。

ボタンがトラックパッドと一体化することにより、トラックパッド自体の操作領域が広がりましたから、とりあえず本体のみで使用する限りは問題ないのかも知れません。その場合でもマルチディスプレイでは、上記の操作が必要になる場面があると考えられますので、どうなのかなと。

とは言え、日常の使用ではワイヤレスマウスを使うことになると思うので、ことさら意識する必要はないんですが……。

t0mori さんが気にされている「Firewire が省略された」点は、確かにちょっと残念。残念なんですが、現状の使用状況を省みると、なくても OK なので、個人的にはマイナスポイントにはならないです。

初代 MacBook 所有者として、「いい」と思った点を挙げると……

  • グラフィックチップの刷新
  • 本体デザインの変更

グラフィックチップの刷新は、影響が大きそうです。

Mac OS X のインタフェースって、ハードウェアのグラフィックアクセラレーションの恩恵も大きい印象があるので、全体的によりきびきび動く感じが体感できるんじゃないかと思います。

本体デザインの変更は、やはり一番の「目玉」でしょう。

今所有している MacBook と比べると、200g ほど軽くなっているようです。今の MacBook はほぼ毎日持ち歩いていて、全然苦にならないんですが、軽くなるのは大歓迎。

ユニボディは、格好良いだけじゃなくて、剛性もしっかり取れている印象です。所有している MacBook は、パームレスト部分が黄ばんで交換しましたが、そういう心配もなさそう。

という訳で、いずれは欲しいなぁ……。

ちなみにスティーブ・ジョブズがプレゼンテーションを行なっている Apple のキーノート (基調講演) は、ポッドキャスト (動画) として配信されています (環境によっては iTunes が立ち上がります)

今回の新しい MacBook の紹介プレゼンテーションも早速アップされています。

スティーブ・ジョブズのプレゼンテーションは「現実歪曲空間」とも呼ばれるほどのものなのは有名ですが、英語の教材としても「使える」と個人的に思っています。

何より個人的に「すごく興味のある」分野の話しかしないので、すっと話題に入っていけるというのが大きいとは思いますけど。

スポンサーリンク

出身地分布図

会社で各自の出身地を世界地図にマークしていくという企画 (?) をやっています。

[写真] 出身地分布

さすがにニュージーランドだけは別紙になっています。

全員がマークしたわけではありませんし、あくまでも自己申告で、中にはふざけて関係ない国にフラグを立てている人もいるので、参考程度に。

こうして見ると、アジア人の割合、高いですね。ちなみに日本に一本だけ立てているのが私です。

この分布を見ても、英語ネイティブスピーカーじゃない人も結構いることが分かるかと思います。

「お隣」であるオーストラリアの人が案外少ないのが、ちょっと意外でしょうか。

意外と言えば、ロシアの人がいないのもちょっと意外かもしれません。英会話クラスとかに行くと、それなりの頻度で見かけるのですが。

一度、ロシア人技術者と面接したこともありますし、人材としていない訳ではないと思うので、たまたま現在、いないだけかもしれません。

スポンサーリンク

Re:「Eee PC」でMac OS Xを動かす方法

ネタフルさんの『「Eee PC」でMac OS Xを動かす方法』という記事より

そもそも、Mac OS Xの動くウルトラライトなポータブルノートが無いというのが問題(?)なのですが、こういう探究心というのは嫌いではないです。でっきるっかなでっきるっかな。

いくつか課題もあるみたいです。

[N] 「Eee PC」でMac OS Xを動かす方法

えぇと、一番の課題は以下の部分だと思います。

But, before we get started there are a few things you should know. First and foremost, you're about to violate Mac OS X's licensing agreement, which specifically states that use must be limited to Apple hardware.

Run Mac OS X on an Eee PC - Wired How-To Wiki

要するに Mac OS X のライセンス違反になるということです。

記事を紹介するにしても、ここの部分を「抜き」に紹介してはいけないような気がします。

スポンサーリンク

Re: 日本人の有給休暇消化率

ニュージーランドの現地企業で働くようになって、ほぼ 5 年。日本での勤続期間とほぼ同じだけ働いてきたことになります。

以前にもちらっと触れましたが、休暇については、日本とは異なる印象を持っています。

日本人が1年間に取得できる有給休暇の平均日数は16日。これは最も多く付与されるフランスの37日に比べると半分以下で、アメリカの15日に次いで2番目に少ない日数だった。

日本人の有給休暇消化率は最低 - 欧米主要8カ国との比較調査で | ライフ | マイコミジャーナル

ニュージーランドでは、法律によって、年次有給休暇は年間 20 日 (以上) と決まっています。うちの会社も年間で 20 日の有給休暇を取得できます。

また、うちの会社では、有給休暇とは別に「有休病欠」があります。

私の明細によると現在大体 1 週間近く病欠しても有給扱いになります。病欠は本人以外の家族の病気でも使うことができます。

年俸制なので、残業手当のような給与面での付加的なものは基本的にありません。ただし、休出については、重大なプロジェクトがある場合、代休についてボーナスがあります (1 日の休出に対して 1.5 日分の代休がもらえる)。

ちなみに、うちの会社では休出するともれなく昼食がついてきます。

個人差があるとは思うので、必ずしも「そうだ」とは言い切れないのですが、こちらでは皆普通に休暇を利用している印象を持っています。

最近は分かりませんが、以前には、年次有給休暇以上の休暇を取っている人も見かけました。つまり、無給休暇です。

長期の休暇 (4 週間とか) を取る人も結構います。私もこれまで 2 回ほど一ヶ月の長期休暇を取っています。

日本で働いていたときは、新婚旅行の 2 週間が最長で、5 年間の勤続で年次有休を使い切ることは結局一度もできませんでした。

有給休暇を (欧米に比べて) あまり取らない理由が興味深くて、

日本人が有給休暇をあまり取得できていない理由としては、40%の人が「仕事が忙しく休暇をとっている暇がない」と回答。次いで「もしもの病気や急用などのために、休暇を残しておきたいから」(34%)、「上司や同僚があまり休暇を取っていないため、取りづらい雰囲気だから」(24%)などと続いた。「特に休暇をとる必要を感じない」(20%)という、いかにも仕事人間らしい回答も挙げられた。

日本人の有給休暇消化率は最低 - 欧米主要8カ国との比較調査で | ライフ | マイコミジャーナル

雰囲気て……。

記事の表にある「上司や同僚が休暇を取ることを快く思っていないように感じる」もなんだかなぁ。それはつまり「他の人が休暇を取ることを快く思っていない」って、その人自身が思っているってことでしょう?

私も日本で勤めていた頃は、年次有休を使い切れなかったんですが、回答としては「仕事が忙しい」が当てはまるんでしょうか (「もしものために」という理由も分かりますし、自分もそういう認識があった気がします)。

ただ、私が日本で勤めていた会社では、そもそも基本的に平日の残業・土日出勤などなしで回るような仕事量じゃなかった印象があります。

[2008.08.31 14:30 追記] 思い返してみたら、「休暇をとってもすることが特になかった」というのもあったかもしれません。特に嫁さんと付き合う前などは。「休暇の取り方」に関しては日本にいたときよりもうまくなっているような気がします。

スポンサーリンク

Re: iPhone 3Gの電波受信感度の問題

興味深い記事を見かけました。

iPhone 3G 内部の「欠陥がある」電力制御ソフトウェアこそ、その原因であると語ったことを伝えた。要するに、iPhone 3G は、接続を維持するために、携帯電話基地局に対して、必要以上に多くのパワーを要求するようになっており、複数の iPhone が、同じ基地局へ同時に接続を試みる時に、これが非常に大きな問題を招いてしまう

iPhone 3Gの電波受信感度の問題、電力制御ソフトウェアが原因の可能性:モバイルチャンネル - CNET Japan

3G と呼ばれる携帯電話網は WCDMA という方式を採用しています。

WCDMA の特徴のひとつに「正確な電力制御」があり、それ故に電力効率がよいという謳い文句があります。

今、現在「電力効率が良い」という謳い文句を使っているかどうかは分かりませんが、少なくとも CDMA が発表された当初は、それも利点のひとつに挙げられていました。

余談になりますが、 WCDMA 端末はいわゆるアンテナがアンテナっぽくなっていないものがほとんどですが、それは利用されている周波数帯によるもので、WCDMA だからという訳ではないと私は認識しています。

WCDMA では、基本的にどの端末 (携帯電話) も同じ周波数を利用するので、互いの信号が干渉しています。

もちろんそのままでは、互いの信号が邪魔し合って通信できなくなってしまうので、それぞれの端末が独自の暗号 (直交符号) を利用して、自分の信号だけを抜き出すような工夫がされています。

いくら暗号を使って、自分の信号だけを抜き出すような工夫をしていても、隣で大声で話されるとやはり邪魔になります。

そこで WCDMA では、基地局に繋がる全ての端末ができるだけ「同じ大きさの声 (電波の強さ)」になるように電力をリアルタイムで調整します。

同じ電波の強さというのは、端末が繋がる基地局から見たときの電波の大きさです。従って、基地局から遠い端末は強い電波で、近い端末は弱い電波で通信しています。

つまり WCDMA では、「電力制御のおかげで電力効率が高い」というのはあくまでも結果論副作用で、実際にはきちんと電力制御をしないと通話が成立しない可能性があるというぐらいという重要な技術と言えます。

そうした視点から見ると、

接続を維持するために、携帯電話基地局に対して、必要以上に多くのパワーを要求する

というのは、ちょっと「ひどい」。……ひどいというか、にわかには信じがたい。

電力制御の方法に関しては、キャリア側から厳格に仕様として決まっているはずで、こういうのは基本的に起きないはずなんですが、事前のチェックとかしていないのかな?

少なくとも、DoCoMo では無理なような気がするんですが。

記事には「複数の iPhone」とありますが、記事の内容が事実なら iPhone 以外の端末にも、悪影響を及ぼしているはずです。

スポンサーリンク

オークランドでのプチオフ

2008 年も半分が終わり、あっという間に 3 週間経ってしました。

今月の初め頃、恍惚のほし ★ならびに恍惚のほし★voibloだ JAPAN!? を運営されている ryo-n さんとお会いしました

ryo-n さんは、お仕事でニュージーランドにいらっしゃったのですが、当初、オークランドへ来る予定はないご様子でした。

南島の方に訪問されていて、日本とニュージーランドという距離からすれば、劇的に近い状況でしたが、それでも「東京 - 福岡」ぐらいの距離があります。近くだから会いましょうという距離ではありません。

ところが、悪天候の影響で急遽予定を変更して、オークランドに寄ってからご帰国されるということに……。自宅から車で 15 分もしない場所に宿泊されるとのことで、短い時間ではありましたが、会ってお話ししてきました。

ネット関連で知り合った方とニュージーランドでお会いするのは初めてで、なかなか新鮮な感覚。

ryo-n さんと言えば、恍惚のほし★voibloだ JAPAN!? の前の podcast 、恍惚のほし ★voibloだで「アリゾナ」在住という印象が深く残っています。

911 の影響や保険の話などアメリカならではの話もあったり、TOEIC の点数が低くても海外での英会話は問題ないとか、「日本食材」を求めて買い出しというような同じような苦労話もあったり……。短い時間ではありましたが、濃い時間を過ごすことができたと思います。

(今は日本ですが) ryon-n さんはアリゾナにいらっしゃって、私はニュージーランドにいて、普通では接点のないあろう人々とこうして会って、すっと楽しくお話できるのは不思議な感覚です。ネットの不思議な力を体感している感じがします。

恍惚のほし★voibloだ JAPAN!? : Vol.024 ★気がつけば、夏」では、ご紹介いただき、ありがとうございます。

この podcast の中で「独力で」と仰ってくださいましたが、私自身は謙遜でもなんでもなく、全然「独力」ではないと思っています。

まず、何より嫁さんの協力なしでは、今の私はありえません。娘からもいつもいっぱい力を分けてもらっています。

ニュージーランドに模範としているような家族がいます。親友と言えるのが誇りに思えるような素晴らしい人たちで、彼らにも本当にお世話になっています。他にも多くの人に助けてもらっていてます。

スポンサーリンク

「プレゼンテーションスキル」コースに参加してきた

コミュニティーエデュケーション

こちらでは「コミュニティエデュケーション」と呼ばれる、一般人向けのショートコースがあります。

平日夜や週末など時間帯に高校の校舎を利用して行なわれて、気軽に参加することが出来ます。

平日夜のコースは 2 時間単位で 4 〜 8 セッションあることが多いようです。週末のコースだと 3 時間程度で 1 〜 2 回という感じでしょうか。値段はピンキリですが、 NZ$30 〜 NZ$60 (2,500 円 〜 5,000 円程度) の範囲に収まるものが多いようです。

こちらに来たばかりの頃は、外国人向けの英会話コースや IELTS コースによく参加していました。

語学学校に入るより割安で、日本人率も低いことが多く、結構お薦めです。平日であれば、時間帯が夜なので、昼間は会社に、夜レッスンにということもできます。

今でもコミュニティーエデュケーションのお知らせが来たら、必ず目を通して、面白そうなコースには参加しています。

プレゼンテーションスキル

今日は「プレゼンテーションスキル」のコースに参加してきました。

会社で、これまで数回プレゼンテーションの機会があったり、ミーティングでも発言を求められることが多くなってきて、「話す」ことに特化したコースに参加してみようかなと思ったのがきっかけです。

朝 9 時からお昼を挟んで 15 時まで。休み時間は全部あわせても 1 時間なく、5 時間以上。こちらが予想していたよりもはるかに英語漬けでした。

生徒は自分を含めて 4 人で、私以外は皆ネイティブスピーカー。ばりばりに仕事をしている方ばかりでした。

「プレゼンテーション」のレッスンなので、話す比率が圧倒的に多いのが特徴です。

単に英語を話すのではなく、ボディランゲージ・アイコンタクト・話すペースや間の取り方など、英語を使って効果的に聴衆とコミュニケートする技術のお勉強という感じ。

「人前で話す」ということを前提にした実践的な内容になっていて、ペアになって「他己紹介」したり、ペアを組んで互いにリハーサルしたり、簡単な実践「シミュレーション」したりします。最後は順番にプレゼンテーションを行ないました。

私が受けた「シミュレーション」では、オーディエンス (聴衆) が疲れて退屈な雰囲気でプレゼンを行なうというシチュエーションが設定されたりしました。

ある政治家のスピーチを題材にした練習も面白かったです。聴衆をやや煽るような感じで、パラグラフを読み上げる練習です。その政治家の伝えたいポイントはどこかを考えて、文章のどこにストレスを置き、どこでポーズを取るか、話す強弱 (「形を作る」と表現していました) はどうするかなどを自分で考えて読み上げます。

普通に英会話をこなすレッスンよりもハードでしたが、なかなか充実した面白いコースでした。

スポンサーリンク

ツリー構造の実装をリファクタリングする

ツリー構造 (多分木 : N 分木) の実装」「ツリー構造の幅優先走査」とツリー構造を表現するコードについて記述してきました。

ここでは、先の記事で使ったコードをリファクタリングして、より汎用性と移植性の高いコードを作成してみたいと思います。

ツリー構造を表現する構造体

これまでのコードでは、ルートノードからの「深さ」を示す depth という変数を構造体の中で保持していました。

ルートノードからの深さは比較的簡単に求めることができるので、あえて持つ必要はありません。

利用頻度を考慮するとあえてメンバーとして保持しなくてもよいケースがほとんどでしょう。むしろこのような特殊な変数を保持することでコードの見通しなどが悪くなってしまったりする危険性があります。

ツリー構造を表現するには、最低限子ノードと隣ノードのポインタを保持しておけばいいわけで、それにノードで保持したい情報を加えた構造体にするのがよいでしょう。

typedef struct node {
  const char* name;
  struct node* child;
  struct node* next;
} node_t;

のように depth をなくし、構造体をシンプルにします。

ノードジェネレイター

これまでのコードでは、以下のような append 関数を用意して、ノードの初期化を行なっていました。

void append(const char* name, node_t* parent, node_t* node)
{
  node->name = name;
  node->depth = 0;
  node->child = NULL;
  node->next = NULL;
  if (parent == NULL) return;
  node->depth = parent->depth + 1;
  if (parent->child == NULL)
  {
    parent->child = node;
  }
  else
  {
    node_t* last = parent->child;
    while (last->next != NULL)
    {
      last = last->next;
    }
    last->next = node;
  }
}

汎用性を高め、後からのメンテナンスを考慮すると、初期化部分は分離した方がよいでしょう。

ふうこさんからのご指摘の通り、node_t のポインタを返り値として返す create 関数を作成してみます。

node_t* create(const char* name)
{
  node_t* node; // *1
  node->name = name;
  node->child = NULL;
  node->next = NULL;
  return node;
}

このようにしたいところですが、このコードは正しく動作しません

*1 で指定している node はローカルな変数なので、create 関数のブロックを抜けると消えてしまいます。malloc 関数を使ってメモリを確保する必要があります。

node_t* create(const char* name)
{
  node_t* node = (node_t*)malloc( sizeof(node_t) );
  if ( node == NULL ) exit( EXIT_FAILURE );
  node->name = name;
  node->child = NULL;
  node->next = NULL;
  return node;
}

ノードデストラクタ

割り当てたメモリは、どこかで解放する必要があります。

今回のような短いプログラムでは、特に必要ではないかもしれませんが、念のため後始末を行なう関数も作成しておきましょう。

void destroy(node_t* node)
{
  free(node);
  node = NULL;
}

ノードを破棄する create 関数は、シンプルで単純に free 関数を呼び出しているだけです。二重に free しないようにノードのポインタに NULL をセットしています。

ついでにツリーそのものを破棄する関数も考えてみます。ルートノードを渡したら、そのツリーの全ノードを解放します。

void destroy_tree(node_t* node)
{
  if (node == NULL) return;
  destroy_tree(node->child);
  destroy_tree(node->next);
  destroy(node);
}

ここでも再帰的にノードを辿っていき、削除を実行しています。

注意して欲しいのは、自身の破棄を再帰した後に行なっているところです。こうしないと、再帰する前に自身が破棄されてしまい、正しく動作しません。

関連関数の変更

ノードの構造体から depth というパラメータを除いたので、ノードを表示する関数などはそのままでは動きません。

「深さ」を外部から引き渡すように変更します。

void append(node_t* parent, node_t* node)
{
  if (parent->child == NULL)
  {
    parent->child = node;
  }
  else
  {
    node_t* last = parent->child;
    while (last->next != NULL)
    {
      last = last->next;
    }
    last->next = node;
  }
}

void display(node_t* node, int depth)
{
  int i;
  for (i=0;i<depth;i++)
  {
    printf(" ");
  }
  printf("- %s\n",node->name);
}

void show_tree_dfs(node_t* node, int depth)
{
  if (node == NULL) return;
  display(node, depth);
  show_tree_dfs(node->child, depth + 1);
  show_tree_dfs(node->next, depth);
}

#define STACK_NUM 100
void show_tree_bfs(node_t* node)
{
  if (node == NULL) return;
  node_t* queue[STACK_NUM];
  int depth = 0;
  int num = 0;
  queue[ num++ ] = node;
  while ( 1 )
  {
    node_t* buf[STACK_NUM];
    int buf_num = 0;
    while ( num != 0 )
    {
      node = queue[ --num ];
      while (node != NULL)
      {
        display(node, depth);
        if (node->child != NULL)
        {
          buf[ buf_num++ ] = node->child;
          if (buf_num >= STACK_NUM) exit( EXIT_FAILURE );
        }
        node = node->next;
      }
    }
    if ( buf_num == 0 ) break;
    while ( buf_num != 0 )
    {
      queue[ num++ ] = buf[ --buf_num ];
      if (num >= STACK_NUM) exit( EXIT_FAILURE );
    }
    depth++;
  }
}

ツリーを深さ優先で再帰的に走査する関数 show_tree_dfs でも「深さ」のパラメータを渡すように変更しています。

子ノードを辿るときだけ、depth + 1 で引き渡しているのがポイントです。

完成

できあがったプログラムは、それなりに長くなってしまうので「続き」に記載します。

続きを読む

スポンサーリンク

12/25