• 検索結果がありません。

第3回 配列とリスト

N/A
N/A
Protected

Academic year: 2021

シェア "第3回 配列とリスト"

Copied!
24
0
0

読み込み中.... (全文を見る)

全文

(1)
(2)

この回の要点

• 連結リストによるリスト

– 連結リストの構造

– 連結リストの利点と欠点

– C言語による連結リストの実現

• ヘッダファイルによるソースファイルの分割

(3)

連結リスト(linked list)

• リストの実現の一種

• リストに含まれる各要素をリンクによって連結した構造

– リンクとは、他のデータへの参照のこと – 各要素は、自分から次のデータへのリンクを持つ – その要素が連なった構造が連結リスト 参照 リンク 名前 個人データ Aさん Bさん Cさん Dさん Eさん Fさん

(4)

連結リストの利点と欠点

• 利点

– データの挿入・削除が簡単=O(1)

– サイズが可変(メモリの上限はある)

• 欠点

– 要素kにアクセスするのにリンクをたどる必要がある=

O(N)

– データ以外にリンク分のメモリが必要

挿入 削除

(5)

双方向連結リスト(double linked list)

• 前後の要素へのリンクを持つ連結リスト

– 要素を逆順にたどることが可能

– 2つのリンクを持つためのメモリが必要

参照 次へ 名前 年齢 個人データ(PD) 参照 前へ NULL Aさん Bさん Cさん Dさん Eさん Fさん 双方向連結リスト NULL

(6)

個人情報型PD

参照 next name age 参照 prev メンバー char *name 名前 int age 年齢 PD *prev,*next 前後のリンク 関数 PD* makePD(const char*,int) PDの生成 void free(PD*) PDの破棄 void insertBefore(PD*,PD*) 前に挿入 void insertAfter(PD*,PD*) 後に挿入 void remove(PD*) 削除 void print(PD*) 表示

(7)

PD.h

#ifndef __PD__h #define __PD__h /*** *** 個人情報 ***/ #include <stdio.h> #include <stdlib.h> #include <string.h> // 個人情報型の宣言

typedef struct PDtag {

struct PDtag *prev,*next; // 前後の個人情報へのリンク char *name; // 名前

int age; // 年齢

(8)

PD.h

// プロトタイプ宣言

PD *makePD(const char *n,int a); // 生成 void free(PD *pd); // 破棄 void insertBefore(PD *pd1,PD *pd2); // pd1の前にpd2を接続 void insertAfter(PD *pd1,PD *pd2); // pd1の後にpd2を接続 void remove(PD *pd); // pdを取り外す void print(PD *pd); // 表示 #endif // __PD__h ここまでが、1回しか読み込まれない

(9)

PD.cc

/*** *** PDの実装 ***/ #include "PD.h" // 個人情報の生成

PD *makePD(const char *n,int a){ PD *pd=(PD*)malloc(sizeof(PD)); pd->prev=pd->next=NULL; pd->name=(char*)malloc(strlen(n)+1); strcpy(pd->name,n); pd->age=a; return pd; } // 個人情報の破棄 void free(PD *pd){ free(pd->name); free((void*)pd);

(10)

PD.cc

// 個人情報pd1の前に個人情報pd2を接続

void insertBefore(PD *pd1,PD *pd2){ if(pd1==NULL || pd2==NULL) return; if(pd1->prev) pd1->prev->next=pd2; pd2->prev=pd1->prev; pd2->next=pd1; pd1->prev=pd2; } 続く pd2 pd1 pd1 前に挿入

(11)

PD.cc

// 個人情報pd1の後ろに個人情報pd2を接続 void insertAfter(PD *pd1,PD *pd2){

if(pd1==NULL || pd2==NULL) return; if(pd1->next) pd1->next->prev=pd2; pd2->prev=pd1; pd2->next=pd1->next; pd1->next=pd2; } pd1 pd2 pd1 後に挿入

(12)

PD.cc

// 個人情報pdを取り外す void remove(PD *pd){ if(pd==NULL) return; if(pd->prev) pd->prev->next=pd->next; if(pd->next) pd->next->prev=pd->prev; pd->prev=pd->next=NULL; } // 個人情報を表示する void print(PD *pd){ printf("%s(%d)",pd->name,pd->age); } pd 削除

(13)

双方向リンクリストListPD

メンバー PD *first,*last 先頭と末尾の要素 int size 要素数 関数 ListPD* makeLlistPD() 生成 void free(ListPD*) 破棄 void addTop(ListPD*,PD*) 先頭に追加 void add(ListPD*,PD*) 末尾に追加 void remove(ListPD*,PD*) 要素を削除 PD* get(ListPD*,int) 取り出し int getSize(ListPD*) 要素数 PD PD PD first PD

(14)

ListPD.h

#ifndef __ListPD__h #define __ListPD__h /*** *** 個人情報のリスト ***/ #include "PD.h" // 個人情報リスト型の宣言 typedef struct { PD *first,*last; // 先頭と末尾の要素 int size; // 要素数 } ListPD; ヘッダファイルの重複読み込みを回避 続く

(15)

ListPD.h

ListPD *makeListPD(); // 個人情報リストの生成 void free(ListPD *lp); // 個人情報リストの破棄 void addTop(ListPD *lp,PD *pd); // リストlpの先頭に個人情報pdを挿入 void add(ListPD *lp,PD *pd); // リストlpの末尾に個人情報pdを追加 void remove(ListPD *lp,PD *pd); // リストlpの要素pdを削除 PD *get(ListPD *lp,int n); // n番目の要素を得る(先頭は0番) int getSize(ListPD *lp); // 要素数 void print(ListPD *lp); // 表示

(16)

ListPD.cc

/*** *** ListPDの実装 ***/ #include "ListPD.h" // 個人情報リストの生成 ListPD *makeListPD(){ ListPD *lp=(ListPD*)malloc(sizeof(ListPD)); lp->first=lp->last=NULL; lp->size=0; return lp; } // 個人情報リストの破棄 void free(ListPD *lp){ free((void*)lp); } 続く

(17)

ListPD.cc

// リストlpの先頭に個人情報pdを挿入 void addTop(ListPD *lp,PD *pd){ if(lp->first==NULL) lp->first=lp->last=pd; else{ insertBefore(lp->first,pd); lp->first=pd; } lp->size++; } PD PD PD PD last first PD pd

(18)

ListPD.cc

// リストlpの末尾に個人情報pdを追加 void add(ListPD *lp,PD *pd){ if(lp->last==NULL) lp->first=lp->last=pd; else{ insertAfter(lp->last,pd); lp->last=pd; } lp->size++; } 続く PD PD PD PD last first PD pd

(19)

ListPD.cc

// 要素pdを削除 void remove(ListPD *lp,PD *pd){ if(lp->first==pd) lp->first=pd->next; if(lp->last==pd) lp->last=pd->prev; remove(pd); lp->size--; } // n番目の要素を得る(先頭は0番) PD *get(ListPD *lp,int n){ PD *p=lp->first;

for(int i=0;i<n && p;i++) p=p->next; return p; PD PD PD last first PD pd

(20)

ListPD.cc

// 要素数 int getSize(ListPD *lp){ return lp->size; } // 表示 void print(ListPD *lp){ PD *p=lp->first; printf("ListPD:(%d):¥n",lp->size); for(int i=1;p;p=p->next,i++){ printf("%d:",i); print(p); printf(" "); } printf("¥n"); }

(21)

ListPDTest.cc

/*** *** 個人情報リストのテスト ***/ #include "ListPD.h" int main(void){ ListPD *lp=makeListPD(); PD *pd; add(lp,makePD("山田",19)); add(lp,pd=makePD("森",50)); add(lp,makePD("田中",23)); print(lp);

(22)

ListPDTest.cc

addTop(lp,makePD("近藤",41)); printf("**before**¥n"); print(lp); remove(lp,pd); printf("**after**¥n"); print(lp); printf("2番目は"); print(get(lp,1)); printf("です。¥n"); }

(23)

課題171023

• 小学校の成績管理をするために、児童の成績データを

双方

向リンクリストに入れて

管理する。このとき、SeisekiDataとい

うクラスはどのような構造にすればよいか、考えて示せ。

ただし、型のみでよい。(関数は不要)

– 成績は国語、算数、理科、社会の4科目 – 児童の情報は、学年、クラス、名前 • 作成方法:自分で考えたクラス構造を、プログラムコードとして ワード文書内に書くこと。ワードのファイル名は、 “scXXXXXX-al171023.docx” • 提出方法:メールで。 •メールの本文中にも学籍番号を氏名を明記すること。 • 提出先:[email protected] • メールタイトル:”アルゴリズム課題171023” ← 厳守!

(24)

連結リスト

終了

参照

関連したドキュメント

When the device is operating as a sink and it receives a Hard Reset or a Power Role Swap, the automatic discharge circuitry and SNK output will be disabled by the host processor

 I hearby report on release the attorney for the Customs procedures (as the attorney for payment of Consumption Tax (This case is only limited to perform regarding to Consumption

Webカメラ とスピーカー 、若しくはイヤホン

The analog to digital converter is a 7−bit A/D which can be used as an event recorder, an input voltage sampler, output voltage sampler, input current sampler, or output

Output current is sensed via a current−sense resistor RCS, which is connected between the CSP and CSN pins. The sensed signal is internally amplified, and this amplified voltage

[r]

第1回 平成27年6月11日 第2回 平成28年4月26日 第3回 平成28年6月24日 第4回 平成28年8月29日

data-set-name BOOLEAN 参照 DataSet true(レポート内に収容). data-reference BOOLEAN データ項目情報