プログラム再構成に関する 特許申請について

データ構造と
アルゴリズム
第五回
知能情報学部
新田直也
連結リスト(復習)

各要素がリンクでつながっているリスト
先頭
5

2
7
3
11
n番目の要素には先頭からn回リンクをたどらなければた
どり着かない.
5
2
7
3
11
5
2
7
3
11
5
2
7
3
11
連結リストによるリストの実装(復習)
read, write: O(n)
 insert: O(n)

先頭
5
2
3
11
7
3
7

delete: O(n)
先頭
5
2
11
連結リストのプログラム(1)

C言語での実装には構造体とポインタを用いる.


Javaではクラスとその参照だけで実装できる.
Webページを考えて見ればよい.
連結リストのプログラム(2)
struct CELL {
int value;
struct CELL *next;
}
CELL
value
next
内容
次ページのアドレス
(ポインタ)
1ページに相当
(構造体)
連結リストのプログラム(3)

ポインタの復習:

p がポインタ(アドレス)なら,*p は pが示す先を表す.
*p
<html>
<body>
<H1>5</H1>
<A HREF=“…”>次へ</A>
</body>
</html>
p

構造体の復習:

s がメンバ m を持つ構造体なら,s.m は s のメンバ m を示す.
s
s.value
s.next
連結リストのプログラム(4)

先頭の要素を示すポインタ(リンク):
struct CELL *header;

ポインタを使ったアクセス:
*header
*((*header).next)
header
(*header).value
(*header).next
(*(*header).next).value
(*(*header).next).next
連結リストのプログラム(5)

リストの最後は?


next が何も指さない(NULL).
リストを順に表示するプログラム:
p
*p
(*p).value
struct CELL *header;
(*p).next
struct CELL *p;
for (p = header; p != NULL; p = (*p).next ) {
printf(“%d\n”, (*p).value);
}

略記法:

(*p).next は p->next と書ける.
( (*p).value も同様.)
連結リストの read, write

read と write
struct CELL *header;
int read(int n) {
struct CELL *p;
p = header;
for (; n > 0; n--) {
if (p == NULL) {
return ERR;
}
p = p->next;
}
return p->value;
}
struct CELL *header;
void write(int n, int e) {
struct CELL *p;
p = header;
for (; n > 0; n--) {
if (p == NULL) {
return;
}
p = p->next;
}
p->value = e;
}
連結リストの insert (1)

insertは?
p
*(p->next)
*p
p->value
p->next
新しいページのURLを r とすると…
r->next = p->next;
p->next = r;
連結リストの insert (2)

新しいページをどうやって作る? そのURLは?
→ malloc 関数

void *malloc(int n);
n バイトのメモリを確保し,その先頭アドレスを返す.
struct CELL *r;
r = malloc(sizeof(struct CELL));
CELL構造体1つ分のメモリサイズ
連結リストの insert (3)

insert
void insert(int n, int e) {
struct CELL *p;
struct CELL *r;
r = malloc(sizeof(struct CELL));
r->value = e;
if (n == 0) {
r->next = header;
header = r;
} else {
n--;
p = header;
for (; n > 0; n--) {
if (p == NULL) return;
p = p->next;
}
r->next = p->next;
p->next = r;
}
}
連結リストの insert (4)

バグを含んだ insert
void insert(int n, int e) {
struct CELL *p;
struct CELL c;
c.value = e;
if (n == 0) {
c.next = header;
header = &c;
} else {
n--;
p = header;
for (; n > 0; n--) {
if (p == NULL) return;
p = p->next;
}
c.next = p->next;
p->next = &c;
}
}
復帰時に c が消えてしまう!
連結リストの delete(1)

p
deleteは?
*(p->next)
*p
p->value
p->next
(p->next)->next
削除ページの直前のページのURLを p とすると…
p->next = (p->next)->next;
連結リストの delete (2)

リンクを切っただけではページは削除されない.
ページ自体を削除するには?
→ free 関数

void free(void *p);
p から始まるメモリを解放する.
r = (p->next)->next ;
free(p->next);
p->next = r;