数据结构——链表(3)

来源:互联网 发布:ledv3.zh3软件下载 编辑:程序博客网 时间:2024/06/05 05:28

链表是什么

现在我们可以回头总结一下我们的链表:
- 链表是一个由节点组成的一条链。
- 每个节点包含两条信息:
- 序列中存储的是一些数据
- 节点中有指向列表中下一个节点的链接。
- 我们可以从第一个单元格开始跟随着link指针,遍历整个链表。
如同下图所示(左边是一个节点,右边是由节点组成的链表)
这里写图片描述 这里写图片描述
- 链表是用于存储元素序列的数据结构。
- 每个元素与其他元素分开存储。
- 然后将这些元素链接在一起成为一个序列
例如我们从尾部插入一个元素,过程如下:
这里写图片描述
这里写图片描述
这里写图片描述
从中间插入元素过程如下:
这里写图片描述
这里写图片描述
删除元素如下:
这里写图片描述

为什么要使用链表?

  • 可以高效效地将新元素拼接到列表中,或者删除列表中任何位置的现有元素。
  • 可以避免做大量的复制和移动步骤。
  • 有一些可以权衡的地方,我们稍后会看到。

为了简单起见,假设我们正在构建一个链接的字符串列表。我们可以将链表中的一个节点表示为一个结构:

struct Node {            string value;            /* ? */ next;        };

那么问题来了,这里的next是什么类型呢?显然我们指向的是下一个节点,当然是指向Node类型的指针了,所以应该这样写:

struct Node {            string value;            Node* next;        };

发现没,这个结构居然是被递归定义的!!,也就是说每生成一个新的节点,就必然有一个指向下一个节点的指针生成。
在分析链表的过程中,一定要记住,我们是需要画图理解的!!!
这里写图片描述

链表的传递

在Peter Jackson的电影《指环王》——“国王回归”中,Rohan通过山顶的一连串信号火灾警告了Gondor的危险。 这个场景是一个很好的例子,说明了在链表中传递消息的这个想法。
这里写图片描述

我们来模拟一下这个过程,假如我们要点燃两座城市,如下图,我们第一步,先建立一个链接:
1. Make this linked list
这里写图片描述
2.Light the fires….
首先,我们要创建一个tower,里面包含了这个地方的名字,当然还有包括它链接的下一个城市,那么它应该是这样的:

struct Tower{    string name;/*这个城市的名称*/    Tower* link;/*链接下一个城市的指针*/};

接下来,我们应该是创建第一个节点:

// 为什么我们要从最后一个节点开始?因为它的成员是确定的Tower * head = new Tower; head->name = “San Jose”;head->link = NULL;

建立完之后我们要做什么呢?我们当然将它链接到下一个节点,但是下一个节点我们又不知道在哪,所以我们需要自己建立一个:

//创建一个节点,并返回一个指向当前节点的指针 Tower *createTower(string name, Tower *link){    Tower *tp = new Tower;   //在heap中新建一个节点,并为此赋值     tp->name = name;     tp->link = link;    return tp;  //返回的是一个指针,指向此时的节点 }

接下来我们要把他们串起来:

    head = createTower("Santa Clara", head);    head = createTower("Mountain View", head);    head = createTower("Palo Alto", head);    head = createTower("Menlo Park", head);    head = createTower("Redwood City", head);    head = createTower("Millbrae", head);    head = createTower("Bayshore", head);    head = createTower("San Francisco", head);

当调用第一个createTower的时候,他这样执行(2)过程,为了按照要求,我也画图分析
这里写图片描述
最后我们展示一下我们的链表:

//遍历 void signal(Tower *start) {   if (start != NULL) {      cout << "Lighting " << start->name << endl;      signal(start->link);//再次执行signal函数,参数指向下一个节点(是整一个节点)    }}

当节点不为空时,输出节点的数据。从头到尾遍历。

我们最后测试一下

#include <iostream>using namespace std;/*声明部分*/ struct Tower{    string name;    Tower* link;};/*函数声明*/ Tower *createTower(string name, Tower* link);void signal(Tower *start);/*main函数*/ int main(){    /*创建最后应该被点燃的城市*/     Tower * head = new Tower;     head -> name = "San Jose";    head -> link = NULL;    /*利用链表,将他们串起来*/     head = createTower("Santa Clara", head);    head = createTower("Mountain View", head);    head = createTower("Palo Alto", head);    head = createTower("Menlo Park", head);    head = createTower("Redwood City", head);    head = createTower("Millbrae", head);    head = createTower("Bayshore", head);    head = createTower("San Francisco", head); /*这里是我们的第一个初始节点                                                 *相当于从后数的最后一个节点      /*标记我们的链表,即从我们的头结点开始遍历*/     signal(head);}//创建一个节点,并返回一个指向当前节点的指针 Tower *createTower(string name, Tower *link){    Tower *tp = new Tower;   //在heap中新建一个节点,并为此赋值     tp->name = name;    tp->link = link;    return tp;  //返回的是一个指针,指向此时的节点 }//遍历 void signal(Tower *start) {   if (start != NULL) {      cout << "Lighting " << start->name << endl;      signal(start->link);//再次执行signal函数,参数指向下一个节点(是整一个节点)    }}

测试结果:
这里写图片描述
由此我们得到一般的节点的结构组成:

struct Node{   int value;    /* The value of this elem    */   Node *link;   /* Pointer to the next node */};
原创粉丝点击