线性链表
(准备分几块来考虑,这样我就能多水几篇文章了)
- 基本线性链表
- 环形链表
- 双向链表
双向环形链表(感觉这个就简单提一下吧)和一些链表比较有趣的习题- 静态链表
首先给一下为什么要整链表这个东西,就是为了折磨人的,其实最开始只有数组的时候,因为数组的长度改变起来非常麻烦(其实想改变的话就是动态数组,具体我也没试过),然后dl就发明了链表。所谓链表,就是猴子捞月,一只猴子(数据域)用手(指向下一个链表的指针域)抓着下一个猴子的尾巴(指针),这样挂起来就是一个链表了。
很明显,第一个猴子没有抓尾巴,也就是前面没有猴子(没有前驱),最后一个猴子的尾巴没有人抓(没有后继),剩余的猴子都是抓着别人的尾巴并且被别人抓着。
个人还是喜欢带一个头节点,就是在第一个存储数据的结点前面再加一个,不放东西,然后指向第一个存储内容的结点,这样对操作比较友好。
图,将就着看吧。
然后呢,贴一下结构体的样子
struct link
{
int data;
struct link* next;
};
数值域简单一点,就一个整型变量
emmm感觉链表第一个难点就是遍历上了吧,当时自己看链表也是,啥都能看懂,一写就是错(别骂了别骂了,老菜鸡了),其实遍历和查找,以及后面的删除特定结点,在特定位置插入,都是联系很大的,所以第一个贴怎么创建链表(别问,问就是刚才忘了)
struct link* New()//尾插法创建链表
{
struct link* head=(struct link* )malloc(sizeof(struct link));
head->next=NULL;//初始化也比较重要
cout << "Do you want a new code?"<<endl;
char a;
cin>>a;
struct link* p=head;
while(a=='y')//a是y就一直通过,创建新节点
{
cout << "Input the data:"<<endl;
int data;
cin>>data;
struct link* pr=(struct link* )malloc(sizeof(struct link));
pr->data=data;
pr->next=p->next;//这两个是将新的连接到原来的链表,切记不要把链断开了
p->next=pr;
p=p->next;//尾结点的指针后移
cout << "Do you want more?"<<endl;
cin>>a;
}
return head;
}
这个东西感觉其实就是怕指针不知道跑哪去了,那个是真的烦,然后头插法原理都是一样说白了就是把链表的指针指向改一下,画个图就差不多了。
遍历:(*2)
struct link* p=head->next;
while(p)
{
cout<<p->data;
p=p->next;
}
for(struct link* p=head->next;p;p=p->next)
cout<<p->data;
总之就是想好最后一个元素,别指向他的下一个并访问数据就行了(说多了都是泪啊,当时就这样编译通过了,但就是没有结果。
因为是malloc创建的空间,所以还需要free掉,这个过程也就是遍历,然后用一个新的指针指向当前要删除的指针,遍历的指针往后走,不然就会把当前的指针释放了,找不到后面的结点。
然后给数据让你删除这个结点就是遍历&删除单一节点,记得把链表再次连接上就行了,空表不能删除,且表头表尾这样的边界条件要考虑一下。
插入也是这样,在某一个结点后面插入,或者头插尾插的,考虑边界条件就完了,链表可以说是不存在插不进去的情况的。
链表的adt操作基本上用画图就能想个差不多,然后还是小心边界条件吧
hello world级的C++,如果代码有问题,dl一定要指出哈。