数据结构——链表(3)

链表是什么

现在我们可以回头总结一下我们的链表:
- 链表是一个由节点组成的一条链。
- 每个节点包含两条信息:
- 序列中存储的是一些数据
- 节点中有指向列表中下一个节点的链接。
- 我们可以从第一个单元格开始跟随着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 */
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值