书中的例子是,在多座岛屿间规划航线,并记录,将岛屿做为节点,数据结构以下node
typedef struct island { char *name; char *opens; char *closes; struct island *next; } island;
注意,递归结构(含有指向相同类型的指针)不能为匿名结构,结构中相同类型的指针,在c语法中不容许经过别名来声明它。git
建立create,display,release函数
github
create:数据结构
island *create(char *name) { island *i = malloc(sizeof(island)); i->name = strdup(name); i->opens = "09:00"; i->closes = "17:00"; i->next = NULL; return i; }
分配sizeof(island)大小的堆内存,并将地址给i,malloc的返回值是void*类型,能够充当任何类型指针赋值操做的右值,可是有的编译器可能会警告。函数
给成员赋值:i->name=strdup(name);strdup的含义是在内存中拷贝name,并返回地址,返回值类型为char* ,之因此这么作,是由于name只是用作接收输入的字符串,在内存中的位置固定,且内容会不断更新,若是直接使用name,那么就会有多个节点(i->name)指向同一个地址,结果就是,多个岛屿的名字都是最后一次输入的那个。spa
i->next=NULL;因为建立岛屿时不知道航线的下一个目的地是哪,因此逻辑上要置空,还有一个缘由就是,若是不把指针置为NULL,那么指向的内存位置是不肯定的,容易致使意想不到的问题。指针
display:code
void display(island *start) { island *i = start; for (; i != NULL; i = i->next) printf("Name:%s\n open:%s-%s\n", i->name, i->opens, i->closes); }
将链表(航线)的起始指针传入,使用一个island类型的指针进行遍历,这个指针充当的是游标/迭代器。
递归
release:释放内存内存
void release(island *start) { island *i = start; island *next = NULL; for (; i != NULL; i = next) { next = i->next; free(i->name); free(i); } printf("finish releasing.\n"); }
使用两个island类型指针从起始位置开始进行顺序释放。逻辑步骤:将i指向起始位置,若是i指向的位置的next不为空,next指向起始节点的下一个节点,释放i,将i指向next指向的位置,而后循环。
free()接收一个void*指针,返回值类型为void,注意一点:free(i)以前,要先把i->name释放掉,还记得吗,咱们用strdup拷贝的name,若是直接free(i),那么拷贝的这个name的那部份内存,就再也访问不到了,没有人知道他的地址,形成内存泄漏,free函数并无那么智能,因此咱们要手动的将这部份内存释放掉,而后再free(i)。
main函数:
int main() { printf("Game on\n"); island *start = NULL; //i as a iterator island *i = NULL; island *node = NULL; char name[80]; for (; fgets(name, 80, stdin); i = node) { if (name[strlen(name) - 1] == '\n') name[strlen(name) - 1] = 0; //node leads to a piece of storage which contains the new island,the 'node' pointer changes every time you create a new island. node = create(name); if (start == NULL) { start = node; } if (i != NULL) { i->next = node; } } display(start); release(start); return 0; }
建立3个island指针,start表明该链表(航线)的起始位置,i做为迭代器将多个节点串联起来,node是新建立的island,每次建立都会更新node的地址,链表中每一个节点只是一段内存(连续或不连续),并无实际的名称。
逻辑步骤:接收一个island名,建立island,用node指针标记这一新建节点,若是当前start为空,将start赋值为node,若是i不为空,将i->next指向node,最后i=node,将i指向新建立的节点(为链接下一个节点作准备),循环这一步骤。完成这一系列操做后,node,i,i->next彷佛都指向同一块内存。
单链表的建立在逻辑上绝对不会有太大出入,一个递归结构做为节点,循环建立节点,用一个临时指针串联全部节点,只start起始指针标记这一链表。
代码已上传到github:https://github.com/AlexTuan1024/egsonhfc.git