キャラ配布(コイカツ)
链表这一结构大家想来并不陌生,但是落实到代码上,本人认为还是有一些小问题。推此即彼,私以为有必要对此小作总结,如下示:
(1)头结点是什么
头结点是我们的链表中那个没有数据域的节点,通过头结点,可以将原本的需要特殊处理的头插法变为不需要特殊处理的一般方式,于此意义,头结点如同一座桥梁,深刻发挥着自己的作用。于是下方内容将从有头结点入手。
#include<iostream> using namespace std; // 这里一个十分有意思的操作提问: // LinkList 和 LNode*有什么不同 // 答案是,没什么本质不同,只不过使用LNode*是想表明这是一个节点 // 而使用LinkList则是想表明,这是我链表的头结点 typedef struct LNode{ int data; struct LNode* next; }LNode, *LinkList; // 事实上,这个head结点是十分重要的,他应该是一个外部变量,因为头结点应该是一直存在的 // 而不应该是一个内部变量,就算是,也要通过函数返回才可以 struct Node * head; // 注意这里传入的是引用,引用其实就是地址 // 说明最后我们是要改变这个LinkList的 void init(LinkList &L){ // 很多人会纠结如何去理解L,其实L既是指针,也是内存 // 当我们用箭头表示链表时,箭头的终点,也可以看做一个块 // 所以这其实应该看做是一个整体,既是箭头,又是节点内存块 // 注意这里L是头结点,但不是头指针哦 L = new LNode; // 这里为空是为了保证我们的尾结点最后一定为NULL L->next = NULL; } LinkList head_insert(LinkList &L){ LNode* tmp ; int x; scanf("%d",&x); while(x != -1){ // tmp是我们第一个存储数据的节点!!! tmp = new LNode; tmp->data = x; tmp->next = L->next; L->next = tmp; // 但是我们不需要头结点head其实 // 因为L本身其实就是我们的头结点的头指针了,他不会变 // 因为头结点永远是第一个! scanf("%d",&x); // 这里返回了L,但是注意,L传入的时候就是一个地址了,所以这里不会有问题了 } return L; }
// 这个代码基本上包括三种情况:
// 第一个循环中,我们的st[j]表明那些还没有被标记的点
// 然后呢,肯定会t == -1找到其中一个,但是,这个循环表明,这不是最后一个
// 后续还会有其他的操作,什么操作呢?
// 那就是继续看这个dist[t]是不是最小的了,如果dist[t]不是最小的,这说明
// dist还有发展的空间,t可能成为j,而且还会有这个情况,一个是dist[t]确实已经
// 不是无穷了,也可能是无穷,这并不重要,重要的是还有后续操作哦!
// 那就是dist[j]可能更小,而dist[j]是一个,因为只有与其直接相连的,dist才不是无穷
// 因此dist会逐渐转移!!!