链表

链表

我们定义每个节点的结构如下:

struct Node{
	int Element;
	struct Node* next;
};

每个节点都包含了元素和指向下一个结构的指针。通过这些指针可以将一个个节点串起来从而形成了一个链表。

链表的插入操作

在这里插入图片描述
在这里,我们想把temp节点插入在node节点的后面,

  1. temp->next = node->next; 先将temp的next指向node的下一个节点
  2. node->next = temp; 然后将node的next指向temp

必须按照上面的顺序。

链表的删除操作

在这里插入图片描述
这里我们想要删除node节点,此时必须找到node的前一个节点pre,然后使pre的next指向node的下一个节点

  1. pre->next = node->next
  2. free(node)

使用虚拟的头结点(dummy head node)

我们在设计链表的插入和删除操作时,要考虑到特殊的情况。
我们想把节点插入在第一个节点的前面应该怎么做?直接使temp->next=node,并将temp设置为头节点。我们想将第一个节点删除时,pre是不存在的,这时只需要将head->next设置为头结点。但是这样做常常需要额外的判断并另外写代码。我们可以给链表添加一个虚拟的头结点,使得插入和删除操作并不需要特别去考虑第一个节点的情况。
在这里插入图片描述

struct Node
{
    int Element;
    struct Node *next;
    Node():Element(0),next(nullptr){}
    Node(int x):Element(x),next(nullptr){}
};

class List
{
  public:
    struct Node *node;   

    List()
    {
        node = new Node();  //新建链表时,配置一个节点空间,并使node指向他,作为虚拟的头结点
    }

    //在位置p后面插入一个节点
    void Insert(struct Node *p, int value)
    {
        struct Node *temp = new Node(value);
        temp->next = p->next;
        p->next = temp;
    }
    void Delete(struct Node*p) 
    {
        struct Node *temp;
        for (temp = node; temp != nullptr;temp=temp->next)
        {
            if(temp->next == p)
            {
                temp->next = p->next;
                delete p;
                return;
            }
        }
    }
};

双向循环链表(Doubly Linked Circular Lists)

双向循环链表的节点定义

struct node
{
	struct node* next;  
    struct node* prev; //多了一个指向前面一个节点的指针
    int data;
};

在这里插入图片描述

多重链表

多重链表可以用来表示树,图等数据结构。
例如: 如果有一个大学有40000名学生和2500门课程。我们想列出某次选课后,选某一门课的所有学生,或是列出某个学生选的所有的课。
说明: 当然,一种方法是使用二维矩阵来表示,但这会浪费绝大多数存储空间(矩阵中绝大多数是0),因为课程选的人数有限,而学生选的课也不可能会达到2500.所以我们应该想办法使用多重链表来表示这一个稀疏矩阵。
在这里插入图片描述
在这里插入图片描述

不用指针实现链表

有些语言并不支持指针,我们可以使用数组的方式实现链表,好像又叫做cursor implementation
上面的链表使用到指针的地方有:

  1. 数据存储在一个结构中,这个结构中有一个next指针指向下一个结构
  2. 我们使用malloc和free来申请和释放内存空间

只需要将上面的两条用其他的方法模拟出来就能摆脱指针了。
维基百科里的例子:
如果链表里的节点是下面这样的结构,并注意,每一个节点都存储在一个数组中,next表示指向的下一个节点的数组下标。这样,我们将数组的index类比了节点的地址。

record Entry {
    integer next; // index of next entry in array
    integer prev; // previous entry (if double-linked)
    string name;
    real balance;
 }

按照如下的方式新建一个数组实现的链表

integer listHead       //存储链表的第一个结点在数组中的下标
Entry Records[1000]   //所有节点

链表可以按如下的方式形成,-1作为链表的结束,listhead为链表的头结点:
在这里插入图片描述
链表的遍历方法:

i := listHead
while i ≥ 0 // loop through the list
     print i, Records[i].name, Records[i].balance // print entry
     i := Records[i].next    //移到下一个节点
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值