大一上半学期就学了链表,但是当时并没有听得特别明白……
现在参考了slandarer老师的https://blog.csdn.net/slandarer/article/details/91863177
然后自己又琢磨了半天,总算是搞明白链表的建立了…
我看老师的博客还是需要思考思考的,我就把我的思考结果记下来了。我感觉,这是最生动形象的想法了!当然看官请轻喷咯emm
slandarer老师给我的启迪
slandarer老师有一点讲的特别形象:链表的每个节点就像是一个抽屉。
这个抽屉中,有存放的货物,也有记着上一个抽屉和下一个抽屉的摆放位置的纸条。
抽屉的定义
抽屉好写,就是一个简单的结构体,我们可以看这个抽屉的写法:
struct Node
{
int data; //抽屉里头塞的东西
Node* next; //上一个抽屉的地址纸条
Node* last; //下一个抽屉的地址纸条
};
昂,这个算是一个最简单的抽屉了,里面只塞一个int类型的值。
创建抽屉的过程
代码如下,分析如注释:
Node* create_middle_list(int n)
{
Node* head, * middle, * end;
head = new Node[sizeof(Node)];
end = head;
//这个时候,end指针和head指针指向的内存空间是相同的,
//也就是说对end所指内存空间的一系列操作,实质上就是
//对head所指内存空间的一系列操作。
//下面的程序中,
//只要没有给end指针重新赋值,那么就是在对head进行操作。
for (int i = 0; i < n; i++)
{
middle = new Node[sizeof(Node)];
//为中间节点开辟内存空间
cout << "input the number:" << endl;
cin >> middle->data;
//往中间节点存入数据
end->next = middle;
//这个时候,说是end->next=middle,其实也可以
//说是head->next=middle。即把head和end所指那块
//空间里的next纸条上写成middle的地址。
//从一个方面看,这是对end的操作;
//从另一个方面看,也就是【头节点存储了下一个节点的地址了】。
middle->last = end;
//这个时候,把middle->的last存成了end节点的地址
//但是这个时候end这个指针还没有变化哈!
//所以其实相当于把middle->last存成了head节点的地址。
//换句话说,也就是使得normal这个中间节点的上一个节点是head。
end = middle;
//这个时候,把middle所指内存空间的地址也给了end
//也就说明了end指向的是刚创建好的middle
//也就是说,middle这个时候也就成了一个尾节点了。
//那么现在能看懂为什么上面所有的能对head操作的地方都要写end了吗?
//其实我相信你是可以看懂的。
//因为,这是一个循环,循环的次数n就是要创建的中间节点的个数。
//我每一次创建新节点的操作,
//其实就是对上一遍循环创建好的最后一个节点做动作
//所以其实相当于在用end跟踪最后一个节点
//每一次添加结点的时候都用end来处理
//就能够“追踪到”并且“修改”上次创建好的最后一个节点了。
//也就是说,可以在上一次创建好的尾节点后面再缀节点了。
//看到这里,重新看一遍上面的程序,把head节点这个词换成
//“上次循环创建好的尾节点”这个词
//就能很好的理解创建链表的整个过程了。
//但是!这个循环之后还没完,这只是“造了足够多个抽屉”,
//可是最后一个抽屉和第一个抽屉里面还有没写字的纸条呢,
//得把它们也写上东西。
}
end->next = NULL;
//尾节点没有下一个
//当然要是想要成环的话也可以写成head,
//当然也要记住给end里的data也赋个值。
head->last = NULL;
//头节点没有上一个
//当然要是想要成环的话也可以写end,
//但是要记住给head里的data也赋个值。
return head;
//返回头节点的地址值,方便之后的其他一系列操作。
}
以上就是最简单的链表如何建立!积累了。