二分木の実装

Algorithms and Data Structures on C
二分木の実装
Algorithms and Data Structures on C
この回の要点
• 二分木のC言語による実装を理解する
• 再帰呼び出しによる木のなぞりの実装を理解する
• 関数ポインタを使った汎用処理の実装を理解する
Algorithms and Data Structures on C
実装コードの構成
• 汎用的構造
• 各ノードはvoid*を持つ
• 二分木のノード
• BinTreeNode.h
• BinTreeNode.cc
• 二分木
• BinTree.h
• BinTree.cc
• テスト用
• TestBinTree.cc
Algorithms and Data Structures on C
BinTreeNode.h
#ifndef __BinTreeNode__h
#define __BinTreeNode__h
/***
*** 二分木ノード
***/
#include <stdio.h>
#include <stdlib.h>
// ノード型
typedef struct BinTreeNodeTag {
struct BinTreeNodeTag *parent;
struct BinTreeNodeTag *left,*right;
void *data;
} BinTreeNode;
続く
Algorithms and Data Structures on C
BinTreeNode.h
// プロトタイプ宣言
BinTreeNode *makeBinTreeNode(void*);
BinTreeNode *makeBinTreeNode(void*,
BinTreeNode*,BinTreeNode*);
void freeBinTreeNode(BinTreeNode*);
void setLeft(BinTreeNode*,BinTreeNode*);
void setRight(BinTreeNode*,BinTreeNode*);
void setData(BinTreeNode*,void*);
#endif // __BinTreeNode__h
Algorithms and Data Structures on C
BinTreeNode.cc
/***
*** 二分木ノードの実装
***/
#include "BinTreeNode.h"
// 生成
BinTreeNode *makeBinTreeNode(void *d){
BinTreeNode *n=(BinTreeNode*)malloc(sizeof(BinTreeNode));
n->data=d;
n->parent=n->left=n->right=NULL;
return n;
}
続く
Algorithms and Data Structures on C
BinTreeNode.cc
// 子ノードを指定して生成
BinTreeNode *makeBinTreeNode(void *d,
BinTreeNode *nl,BinTreeNode *nr){
BinTreeNode *n=(BinTreeNode*)malloc(sizeof(BinTreeNode));
n->data=d;
n->parent=NULL;
setLeft(n,nl);
setRight(n,nr);
return n;
}
// 破棄
void freeBinTreeNode(BinTreeNode *n){
free(n);
}
続く
Algorithms and Data Structures on C
BinTreeNode.cc
// nの左にlを設定する
void setLeft(BinTreeNode *n,BinTreeNode *l){
n->left=l;
if(l) l->parent=n;
}
// nの右にrを設定する
void setRight(BinTreeNode *n,BinTreeNode *r){
n->right=r;
if(r) r->parent=n;
}
// nにデータを設定する
void setData(BinTreeNode *n,void *d){
n->data=d;
}
Algorithms and Data Structures on C
BinTreeNodeの使い方
BinTreeNode *n1;
n1=makeBinTreeNode(makePD(“山田”,19));
NULL
BinTreeNode
parent
name=“山田”
age=19
void*
left
NULL
PD
right
NULL
BinTreeNode *n2;
n2=makeBinTreeNode(makePD(“森”,55));
単独ノードの
作成
Algorithms and Data Structures on C
BinTreeNodeの使い方
子ノードを持つ
ノードの作成
BinTreeNode *n3;
n3=makeBinTreeNode(makePD(“中村”,32),n1,n2);
NULL
BinTreeNode
parent
void*
left
parent
right
PD
parent
name=“山田”
age=19
void*
NULL
name=“中村”
age=32
BinTreeNode
BinTreeNode
left
PD
right
NULL
name=“森”
age=55
void*
left
NULL
PD
right
NULL
Algorithms and Data Structures on C
BinTree.h
#ifndef __BinTree__h
#define __BinTree__h
/***
*** 二分木
***/
#include "BinTreeNode.h"
// 二分木型
typedef struct {
BInTreeNode *root;
} BinTree;
続く
Algorithms and Data Structures on C
BinTree.h
// プロトタイプ宣言
BinTree *makeBinTree();
BinTree *makeBinTree(BinTreeNode*);
void freeBinTree(BinTree*);
void setRoot(BinTree*,BinTreeNode*);
void traverse(BinTree*,int,void(*)(void*));
#endif // __BinTree__h
Algorithms and Data Structures on C
BinTree.cc
/***
*** 二分木
***/
#include "BinTree.h"
// 生成
BinTree *makeBinTree(){
BinTree *t=(BinTree*)malloc(sizeof(BinTree));
t->root=NULL;
return t;
}
// 根ノードを指定して生成
BinTree *makeBinTree(BinTreeNode *r){
BinTree *t=(BinTree*)malloc(sizeof(BinTree));
t->root=r;
return t;
}
続く
Algorithms and Data Structures on C
BinTree.cc
// 根ノードの設定
void setRoot(BinTree *t,BinTreeNode *r){
t->root=r;
}
// 行きがけ順のなぞり
void traversePreOrder(BinTreeNode *n,void(*func)(void*)){
func(n->data);
if(n->left) traversePreOrder(n->left,func);
if(n->right) traversePreOrder(n->right,func);
}
// 通りがけ順のなぞり
void traverseInOrder(BinTreeNode *n,void(*func)(void*)){
if(n->left) traverseInOrder(n->left,func);
func(n->data);
if(n->right) traverseInOrder(n->right,func);
}
続く
Algorithms and Data Structures on C
BinTree.cc
// 帰りがけ順のなぞり
void traversePostOrder(BinTreeNode *n,void(*func)(void*)){
if(n->left) traversePostOrder(n->left,func);
if(n->right) traversePostOrder(n->right,func);
func(n->data);
}
void traversePostOrderN(BinTreeNode *n,void(*func)(void*)){
if(n->left) traversePostOrder(n->left,func);
if(n->right) traversePostOrder(n->right,func);
func(n);
この関数は、木のノードを全部解放するために
}
内部的に使用する。
続く
Algorithms and Data Structures on C
BinTree.cc
// 破棄(中のノードも破棄する)
void freeBinTreeNode(void *n){
freeBinTreeNode((BinTreeNode*)n);
}
void freeBinTree(BinTree *t){
traversePostOrderN(t->root,freeBinTreeNode);
free(t);
}
// 木のなぞり
void travrse(BinTree *t,int m,void(*func)(void*)){
switch(m){
case 0: traversePreOrder(t->root,func); break;
case 1: traverseInOrder(t->root,func); break;
case 2: traversePostOrder(t->root,func); break;
}
}
Algorithms and Data Structures on C
BinTreeの使い方
根ノード付き
木の作成
BinTree *tree=makeBinTree(n6);
BinTree
root
n6
n5
n3
n1
n2
n4
Algorithms and Data Structures on C
BinTreeのなぞり
void printPD(void *pd){
print((PD*)pd);
printf(“ – ”);
}
...
traverse(tree,0,printPD);
木をなぞりつつ、毎回この関数が呼び出される。
そのとき、引数としてノードの持つデータが渡され
る。(ただしvoid*として)
Algorithms and Data Structures on C
TestBinTree.cc
/*** BinTreeのテスト ***/
#include "BinTree.h"
#include "PD.h"
void printPD(void* pd){
print((PD*)pd);
printf(" - ");
}
int main(){
BinTreeNode *n1,*n2,*n3,*n4,*n5,*n6;
n1=makeBinTreeNode(makePD("山田",18));
n2=makeBinTreeNode(makePD("森",55));
n3=makeBinTreeNode(makePD("中村",32),n1,n2);
n4=makeBinTreeNode(makePD("石田",27));
n5=makeBinTreeNode(makePD("今井",60),NULL,n4);
n6=makeBinTreeNode(makePD("牧",30),n3,n5);
Algorithms and Data Structures on C
TestBinTree.cc
BinTree *tree=makeBinTree(n6);
printf(“***Pre***¥n");
traverse(tree,0,printPD);
printf("¥n");
printf(“***In***¥n");
traverse(tree,1,printPD);
printf("¥n");
printf(“***Post***¥n");
traverse(tree,2,printPD);
printf("¥n");
freeBinTree(tree);
}
Algorithms and Data Structures on C
TestBinTreeの結果
$ TestBinTree
***Pre***
牧(30) - 中村(32) - 山田(18) - 森(55) - 今井(60) - 石田(27) ***In***
山田(18) - 中村(32) - 森(55) - 牧(30) - 今井(60) - 石田(27) ***Post***
山田(18) - 森(55) - 中村(32) - 石田(27) - 今井(60) - 牧(30) -
Algorithms and Data Structures on C
課題141215
• 右の個人情報の木構造を作成し表示せよ。
その後、40歳以上の人の年齢を5歳増や
し、再度表示せよ。
• “Add5PD.cc”とすること。
• 表示順は行きがけ順
• 以下の関数を作って使うこと
山田
(19)
• printPD() : PDを表示する
• addPD() : PDのうち40歳以上の年齢を+5する
森
(55)
• 提出方法:ワードで作成し、プログラムと実行結果を
張り付けること。(文字でも画像でもよい)
•
久永
(53)
プログラムは自分で作ってコードだけでよい。
• 提出先:[email protected]
• メールタイトル:”アルゴリズム課題141215”
• 提出期限:2014年12月21日(日)
牧
(33)
今井
(66)
中村
(35)
川平
(48)
石田
(27)
前田
(50)