我们这篇博文有一个目的。我将告诉你跟编程有关的一些事情。
主要是因为这是面向猫大cpp课的一道项目题来写的博客,所以我们强制使用链表结构。只用单链表已经足够。而且我们用传统的结构体和结构体指针方法,因为这是该课程试图让学生知道的。实际生活中处理这类问题我们有更好的方法,因为无论是刘汝佳,谭浩强还是《实用c++编程指南》和《信息学奥赛一本通》均没有好好介绍动态链表。
关键词:结构体,结构体指针,动态链表,单链表,建表和查找元素
本文假设读者都是上过高中生物内容的,作者当年读的是人教版。本文用肽链来比喻链表以试图加深读者对链表的理解,对记不得这方面知识的人也不会有什么影响阅读的反效果。
链表是由很多结点(node)连结而成的一条链。链表就像一条肽链 (其实最像anal beads。我实在想不到其他比喻啦) 。一个结点连接着它的下一个同类。如何建表,即这条肽链如何生成,涉及到“建立肽键"的过程。链被建立之后,有一个简单的方法来从这条链的起点开始走遍全链,顺便寻找我们所要的信息。
链表有一个起点,有一个终点。有着极强烈c程序语言风格的特征。
链表的每个点,我们把它想象成一个小球。小球的上半球可以盛装很多信息,而下半球只有一个目的:连接下一个这样的结点小球。就好像假如每个结点是一个氨基酸的话,R基团用来保存信息,而它的羧基或者氨基用来连接下一个结点。用c++语言实现,每个结点就是这样:
struct Node{ int a,b,c; char *s; double d,e,f;//想要更多?继续加。 Node* next;//下一个是谁? };Node是我们自己创建的类型,和int, char, double 差不多。现在让我们像用int 一样来用 Node。 在c++语言里,这样似乎是合法的。无需写成struct Node 这样累赘的样子。毕竟c已经++了。所以也不会有typedef这种东西。
结点 (氨基酸) 已经有了,让我们来合成肽链吧。
核糖体用来合成肽链。核糖体每次操作两个氨基酸,在他们中间缔结肽键,将这两部分合而为一。链表建表时也差不多。 链表需要有一个起点。起点较为特殊,作为基准,起点一般不存储信息。启动子与其没有强烈的对应关系。 先在内存的一片虚无中生成我们的起点。
struct Node{ int a,b,c; char *s; double d,e,f;//想要更多?继续加。 Node* next;//下一个是谁? }; int main() { Node* head; head = new Node*;使用Node指针(和int指针差不多,就是个指针而已),是因为我们要学习广大程序员大众。这些在编程方面最聪明的人们觉得使用指针来编制数据结构是更好的方法,因为世界上他们写的大部分数据结构程序都用了指针来编写。他们是专业的。使用指针会有很多我们现在或许想不到的好处。我们向专业看齐,在此使用指针。
在内存的广袤空间里现在有了属于我们的基准。它像尺子上的零刻线,是接下来链表的起点。head里一般不存储信息。
大自然使用核糖体来生成肽链。核糖体一次要操作两个氨基酸,在它们中间缔结强力的联系 :肽链。我们用arg1和arg2来代表。argument是自变量的意思。
struct Node{ int a,b,c; char *s; double d,e,f;//想要更多?继续加。 Node* next;//下一个是谁? }; int main() { Node* head; head = new Node*; Node *arg1,*arg2;为链表连接第一个存放着信息的结点吧。取来一个氨基酸,并把它和head连在一起。
arg1=head; arg2= new Node*; arg1->next=arg2; arg1=arg2;以上第三行,就生成了肽键。第四行,核糖体在mRNA上前进了一位,第二位参数arg2已经准备好接受新的氨基酸。
继续延长肽链,直到终止子。
while(要继续延长肽链){ arg2= new Node*; arg1->next=arg2; arg1=arg2; }我们要标记肽链的终点。否则核糖体将不知道它什么时候停止工作。这太残忍了,也会出乱子。我们假设每一个氨基酸都是最后一个要被加到肽链上的氨基酸。
while(要继续延长肽链){ arg2= new Node*; arg2->next=NULL;//下一个?没有了。 arg1->next=arg2; arg1=arg2; }这样会在连接最后一个氨基酸之后真正标记肽链的终止。
成链的同时要把信息也录入。
while(要继续延长肽链){ arg2= new Node*; arg2->next=NULL;//下一个?没有了。 cin>> arg2->information; arg1->next=arg2; arg1=arg2; }核糖体缔结两个氨基酸之间的肽键,然后自身前移一位。继续向前,直到终止。 成链完毕。
从我们的起点head开始,走遍这个链的全程,直到终点。
Node* p=head; while(p->next!=NULL){ p=p->next;//head的下一个也刚好是第一个有效结点 p->information现在悉听先生尊便。 要判断它是不是我要找的信息吗?用if呀。 一般地也就这一个操作吧。 }我们已经可以顺着这条链走遍一次了。那我们现在想做什么都可以了。学生信息管理?不过是一个应用罢了。
/* Name: 链表学生管理 Author: Esther' Date: 15/05/19 14:26 Description: 用动态链表实现学生信息的录入和查找。并用文件输入输出。 */ #include<iostream> #include<cstring> #include<fstream> using namespace std; struct Student{ unsigned long id; char name[36]; float score; Student* next; }; int main() { ifstream fin("CPP_Score.txt"); ofstream fout("out.txt"); Student *head,*arg1,*arg2; head= new Student; arg1=head; double id,score; char name[36]; fout<<"输入id,姓名和成绩。输入0结束录入。\n"; while(fin>>id){ if(id){ fin>>name>>score; arg2=new Student; arg2->next=NULL; arg2->id=id; strcpy(arg2->name,name); arg2->score=score; arg1->next=arg2; arg1=arg2; }else break; } // Student *i=head; // while(i->next!=NULL){ // i=i->next; // fout<< i->id <<" "<< i->name <<" "<< i->score <<endl; // } fout<<"输入学号来查询,输入0结束查询。\n"; while(fin>>id){ if(id==0) break; bool found=0; Student *i=head; while(i->next!=NULL){ i=i->next; if(i->id==id){ found=1; fout<< i->id <<" "<< i->name <<" "<< i->score <<endl; } } if(!found) fout<<"did not find the id\n"; } fin.close();fout.close(); return 0; }