食物网的资料结构Word文档格式.docx
- 文档编号:17114335
- 上传时间:2022-11-28
- 格式:DOCX
- 页数:47
- 大小:219.95KB
食物网的资料结构Word文档格式.docx
《食物网的资料结构Word文档格式.docx》由会员分享,可在线阅读,更多相关《食物网的资料结构Word文档格式.docx(47页珍藏版)》请在冰豆网上搜索。
以一個一維的結構(struct)陣列來儲存各項生物的資料,再定義某些項目之間的關係,藉著這些關係,可建立一個單純的食物網模型。
一、根據方程式(這是簡化版,原版請參考附錄一):
Bi=
+Xi
Qik=Bk*(DC)ik*(FR)k
所定的結構如下:
B:
生物量。
X:
常數。
FR和DR:
和他種生物之間的關係數值。
(B、X、FR和DR的詳細定義參考附錄一)
eaten:
做為「被捕食」的計數器(下面將詳細說明)。
check:
做為此一單位(生物)的檢查碼,用以識別是否已「執行」過)下面將詳細說明)。
以這樣的一個結構做一個單位,在程式開始的時候宣告一個和資料中生物種類個數相同數目的陣列(因此他的個數無法改變------或者說是「要改變有點麻煩」,整個程式會亂亂的)。
下面是程式的執行流程及說明。
二、程式流程說明(參考「三、流程圖」):
1、Input:
先讀入檔案(*.txt),將各數值讀至相對應的陣列元素內。
檔案格式為:
B
FR
X
DR(一個陣列:
捕食者<
->
被捕食者)
單位A
單位B
單位C
單位D
單位E
單位F
-1,
0,
300,
2,
200,
1,
1500,
3,
1000,
400,
1100,
4,
0.3,
0.2,
0.5,
Input.txt
(粗框者)
2、根據方程式,當其中一個單位M的生物量(B)已知時(PS.其他「非B」的資料項不可缺),可以得知捕食M的「捕食者L」的生物量(式i、ii);
及被M捕食的「被捕食者N」的部分生物量(式iii、iv):
(式i、ii)
BM=
+XM(i)
(已知)(已知)(已知)
QML=BL*(DC)ML*(FR)L(ii)
(已知)(可求出)(已知)(已知)
(式iii、iv)
QNL=BM*(DC)NM*(FR)M(iii)
(已知)(已知)(已知)(已知)
BN=QNM+QNX+……+XM(iv)
(無法求得)(已知)(無法求得)(已知)
故只能求得「部分」生物量
3、整個主要過程是在一個while()的迴圈內進行,並用一個bio變數來計數(bio為「未知生物量的單位的個數」,每求得一個單位的生物量即減1,並隨時檢查bio的值;
當bio等於0時,就強制跳出while()迴圈)。
4、程式在執行的時候,會去檢查每個單位的生物量(B)是否為-1(-1代表「未輸入」,以和「生物量為0」做區別);
當生物量(B)「有值」(即不等於-1)時,則呼叫兩個函數,一個可將「捕食者」的生物量求出來(voideater(int));
一個可算出「被捕常者」的部分生物量(voideat(int)),並儲存在一個N乘以N的二維陣列內(N為單位個數)。
5、因為是在while()內,每一次迴圈都會重覆查看單位的生物量,因此設一個檢查碼(intcheck),在笫一次對已知的單位生物量執行過eater()及eat()函數後,笫二次再碰到時會直接跳過,除了簡省時間外,也可以避免「被捕食者」因被重覆執行eater()函數而使生物量(B)的值也被重覆計算。
6、每一個「被捕食者」在所有的「被捕食量」都知道後,即可求出生物量(B),「被捕食量」原來儲存在一個N乘以N的陣列中,因此增設一個變數eaten,紀錄每一單位的「被捕食次數」。
每求出一個「被捕食量」後即減1,當eaten等於0時,就可以呼函數(floatadd(int))進行累加的動作來求出生物量。
eaten的值可在整理資料初值(voidfirst_set())時邊計算得到。
7、當跳出while()迴圈後,程式便會將各生物的生物量(由螢幕)列印出來。
三、流程圖(見次頁):
包含
(1):
主函式的流程-----------------voidmain()。
(2):
副函式eater的流程--------voideater(int)。
(3):
副函式eat的流程-----------voideat(int)。
註:
流程圖只包含主要函式。
(1):
主函式的流程-----------------voidmain()
(2):
副函式eater的流程--------eater(int)
(3):
副函式eat的流程-----------eat(int)
四、程式碼:
(模型一的程式碼)
#include<
iostream.h>
stdio.h>
stdlib.h>
conio.h>
#defineN6//生物的「數量」,因為是陣例結構,故先指定
structchain/*結構定義*/
{
floatbiomass,x,fr,dr[N];
inteaten,check;
};
chainanimal[N];
//宣告結構
floatqik[N][N];
//宣告一陣列(儲存各「被捕食量」用)
intbio=N-1;
//宣告變數bio(流程控制用)
voidread()/*副函式(讀檔用)*/
inti,j;
floatcj;
FILE*fp;
if((fp=fopen("
e:
\\7351420\\input\\chain_3.txt"
"
r"
))==NULL)
{
cout<
<
"
OpenFileError!
!
"
;
exit
(1);
}
for(i=0;
i<
N;
i++)//將各資料讀入
fscanf(fp,"
%f,"
&
cj);
animal[i].biomass=cj;
animal[i].fr=cj;
animal[i].x=cj;
for(j=0;
j<
j++)
animal[i].dr[j]=cj;
fclose(fp);
}
voidfirst_set()/*副函式(初值設定用)*/
i++)//設定eaten和check的初值
animal[i].eaten=0;
animal[i].check=1;
j++)//設定qik陣列的初值
qik[i][j]=0;
i++)//讀入各資料
if(animal[j].dr[i]!
=0)
animal[i].eaten++;
if(animal[i].biomass!
=-1)
animal[i].eaten=-1;
voideater(intuse)/*副函式(算「捕食者」生物量用)*/
inti;
floatcy,cu;
i++)
if(animal[i].dr[use]!
if(animal[i].biomass==-1)
cy=animal[use].biomass-animal[use].x;
cu=animal[i].fr*animal[i].dr[use];
animal[i].biomass=cy/cu;
bio--;
floatadd(intuse)/*副函式(累加)*/
intj;
floatsum=0;
sum=sum+qik[use][j];
return(sum);
voideat(intuse)/*副函式(算「被捕食者」的「部分生物量」用)*/
if(animal[use].dr[j]!
qik[j][use]=animal[use].dr[j]*
animal[use].biomass*
animal[use].fr;
animal[j].eaten--;
//檢查是否有「被捕食者」的生物量已可求得?
if((animal[j].eaten==0)&
&
(animal[j].biomass==-1))
animal[j].biomass=animal[j].x+add(j);
voidmain()/*主函式*/
unsignedlongcount=0;
intuse,i;
read();
//讀檔
first_set();
//初值設定
use=count%N;
while
(1)//while迴圈(整個重點內容!
!
)
if((animal[use].biomass!
=-1)&
(animal[use].check==1))
eater(use);
eat(use);
animal[use].check=0;
if(bio==0)//檢查(如果所有生物的生物量皆「已知」,可跳出迴圈)
break;
count++;
i++)//印出結果
printf("
\n%9.2f"
animal[i].biomass);
\n"
getch();
五、討論:
本來原則上在這一個模型中,在其他「非B」項的資料已知的條件下,只知其中任一位的生物量(B),都可以將其他單位的生物量(B)求出。
但卻有些情況例外。
在一個食物鏈中,不外乎包含幾種基本型:
將生物量「已知」和「未知」的單位之間的關係用表格表示:
笫i種情況
已知
未知
由已知可否求出未知
A
○
笫ii種情況
B、C
○(由A可知C、由C可知B)
A、C
○(由B可知C,由C可知A)
C
A、B
○(C可知A、B)
笫iii種情況
B、C
╳(∵不知道A「分別」對B、C的「被捕食量」,所以無法求得B及C)
A、C
╳(∵單憑B無法求出A,也就無法藉A求出C)
C
A、B
╳(∵單憑C無法求出A,也就無法藉A求出B)
上面的情況,是無法將「所有生物的生物量」找出來的情況。
因為是整個程序上的問題(由公式而來的),所以只能從「除錯」的方向改善------當資料有問題或不足而無法正確執行程式時,會出現提示說明告知使用者(這一點在模型二有改善)。
模型二:
由於模型一用的是「陣列」結構,當輸入單位個數改變時,必須要從程式碼的地方去更改,另外當要在一個已建立的模中新增或移除單位時,以陣列的結構來說都不太方便(新增的時候還可以再宣告一個個別的結構〔struct〕;
但要刪除的時候就會有點麻煩……),而一直重覆執行(新增&
刪除)後也會讓整個模型變的很亂……。
因此,模型二是模型一的延伸,所用的方程式和觀念與模型一同(故在此不贅述),而用鏈結(link)的方式取代陣列。
一、因為鏈結和陣列結構本身的差異,模型二的架構大致上改變了很多(註一)
在結構(struct)宣告方面,包含兩種結構(struct),分別構成兩串環狀鍵結。
如下:
Animalstruct
Chainstruct
Animal結構存放的是一個單位的基本資料,包括名稱;
B、X、FR(定義同前);
temp:
為計算「被捕食量時的暫存空間,後面會再提到」。
eaten_time:
為「被捕食量」次數的計數器,作用同前面的「eaten」。
next:
是一個指標,指到下一個單位。
Chain結構存放的是單位和單位之間的「關係」。
Relation:
存放單位和單位之間的關係(數值)。
Food_che和eater_che:
是檢查碼(下面將詳細說明)。
Food和eater:
都是指標,分別指到relation的「關係人」(food指到「被捕食者」,也就是做為「食物」的那一邊;
eater指到「捕食者」);
next指到下一個「關係」。
陣列中的每一個單位是由「索引」控制的,也就是說,給索引一個值後即可「任意」提取你要的單位中的資料(圖i)。
但鍵結是「循序」的,也就是「找到笫一個單位,才能找到下一個」(圖ii),不能「隨意」的指定,因為他沒有一個像陣列一樣的「索引」。
二、產生鏈結時,需要一個長度和單位個數相同的animalstruct鏈結;
但因為chainstruct存放的是單位和單位之間的「關係」,N個單位就有N*(N-1)/2種關係,也因此,兩者的長度事實上不是相同的(關係的個數在程式中由count(int)這個副函式算出)。
將上面的文字用圖示說明:
chain鏈結存放了單位單位之間的係,而food和eater指標(長在兩旁的箭頭)指向所存關係的「捕食者」和「被捕食者」,即會指到其中一個animal結構(右方圖)中。
執行時,以chainstruct這個鏈結為主軸,程式會先循序檢查所存放的關係值(relation),再依指標(food和eater)找到「關係人」,針對數值做處理。
三、程式的流程和說明(參考「四:
流程圖」):
先讀入檔案(*.txt),將各數值相對應的變數內。
檔案分為兩個,一個存放關於各生物的生物特性(*_1.txt);
另一個存放生物和生物之間的關係(*_2.txt),即一個用來建立animal鍵結(*_1.txt);
一個用來建立chain鍵結(*_2.txt)。
檔案格式如下。
以數據一為列(參考附錄二),其輸入檔為:
*_1.txt*_2.txt
2、資料都讀入後,就開始建立animal和chain這兩個鍵結的關係。
因為*_2.txt這個檔案的內容在建立時,即照著一定的關係:
笫一個數字是A-B的關係;
笫二個是A-C;
笫三個是A-D……,如下:
A-B,A-C,A-D,A-E,……A-N,
B-C,B-D,B-E,……B-N,
C-D,C-E,……C-N,
…………
(依此類推)
所以要建立兩者之間的關係(就是把chain中的food和eater指標分別對應到animal鍵結中的單位),就有一定的順序可循(由副函式establish()建立,此不多述,請參照程碼)。
3、整個主程是在一while()迴圈內進行,並用一個biom變數來計數(bio為「未知生物量的單位的個數」,每求得一個單位的生物量即減1,並隨時檢查biom的值;
4、執行時,以chainstruct這個鏈結為主軸,程式會先循序檢查所存放的關係值(relation),當relation有值時,就會先後分別檢查food和eater所指到的生物(在animal中)的生物量是否有值?
如果有,就可以針對它做處理(沒有的話則略過)。
5、模型二大致上所含單位和模型一相同(只是因為結構的關係不同而用了不同的方式或名稱取代了部分單位的功能)。
temp用來「暫存」生物量,當所有的「被捕食量」沒有全部求出來之前,先放在這;
food_che和eater_che這兩個檢查碼是避免food和eater這兩指標被「重覆使用」而浪費時間而設的(只會做一次)。
這三個變數的詳細作用,請參照程式碼
6、在模型二中,多了一項檢查功能,除了當biom值等於零(代表所有生物的生物量都已知)外,如果while()迴圈跑了一遍,對整個程式的資料卻沒有任何更動的話,也會跳出迴圈,並提示:
「資料不足」訊息。
四、流程圖(見次頁):
包含:
主函式的流程---------------
voidmain_ch2()。
(因為模型二和模型一的差異主要在主函式的部分,其它小細節------程式片斷------都類似,故只列出此部分的程式碼)
五、程式碼:
(模型二的程式碼)
模型二的程式碼分成五個檔案(包含一個*.h檔和四個*.cpp檔):
1、toolbar.cpp:
介面(一個工具列式的介面)。
2、L1_1.cpp、L1_2.cpp和L1_3.cpp:
主要的函式內容,就是模型一的主要功能。
1、toolbar.h
#defineConColorWHITE+(BLUE<
4)
#defineMesColorYELLOW+(BLUE<
#defineLevellColorBLACK+(LIGHTGRAY<
#defineChooseColorYELLOW+(RED<
#defineNormColorWHITE+(BLACK<
#defineMenuColorYELLOW+(GREEN<
#defineUp72
#defineDown80
#defineRight77
#defineLeft75
#defineEnter13
#defineFile0
#defineOption1
#defineHelp2
#defineEsc27
#defineM_top5
#defineM_bottom18
#defineM_left10
#defineM_right50
#defineC_top2
#defineC_bottom25
#defineC_left1
#defineC_right40
#defineD_top2
#defineD_bottom25
#defineD_left41
#defineD_right79
2、toolbar.cpp
alloc.h>
bios.h>
toolbar.h>
//--------------------------------------------------------------------------------------------------------------
char*item[]={"
File"
Option"
Help"
char*menu[3][3]={{"
Load"
Save"
Exit"
},
{"
Help"
Oringin"
}};
charfilename[30];
charfilename2[30];
intitemlen[3]={4,6,7};
//Thelenghofitem
intitemx[3]={2,8,16};
//Theoccationof'
x'
ofitem
intitemy=1;
y'
intcount[3]={3,1,2};
//Thenumberofmenu
intcurrent=-1;
//Torecordwhatmenuisselecte
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 食物 资料 结构
![提示](https://static.bdocx.com/images/bang_tan.gif)