STL list中迭代器
1.链表的结构
链表的结构:
每一个链表上的节点都有三个部分:前指针,值,后指针
分别说明一下这三者的作用:
前指针(pre):指向前一个节点的值
后指针(next):指向后一个节点的值
值:节点上保存的东西
链表是线性结构,由此我们可以知道链表上的各个节点的连接方式就是通过前后指针相连接,要想查找到某个节点只有通过前面的节点或者后面的节点。
缺点:所以要查找链表中的某一个节点的值只有通过遍历的方式去查找!
优点:插入删除某一个节点非常的方便
例如:现在又nod1,nod2,nod3
我们要删除nod2,只要将nod1的后指针指向nod3,nod3的前指针指向nod1,就可以了,操作非常的简洁
但是删除还不能体现链表的特性,插入才是链表的特点!
如要将nod_insert 插入到1和2之间
//插入的节点与前节点连接
nod1.next = nod_insert.val;
nod_insert.pre = nod1.val;
//插入的节点与后节点连接
nod_insert.next = nod2.val;
nod2.pre = nod_insert.val
可以发现,插入一个新的节点只要将新节点与前后的节点连接,当然只是举例还有其他情况没有举例出来。
而数组的那种顺序线性表的因为是按顺序的所以取值非常的方便,但是插入的却是异常的麻烦,要将后面的所有数都后移一位!
2.迭代器的作用
迭代器的声明:
list<type>::iterator it;
由上面的所述可以发现链表跟数组的区别,数组有具有下标,遍历的时候只需要遍历下标就行了,但是链表没有,所以就提出了迭代器的观念。我们可以理解为一个变量,他用来指向我们容器中元素。
我们就可以使用迭代器去遍历我们的链表从而达到我们的目的!
3.通过迭代器获取元素中的值
**迭代器就相当于指针,指向一个地址,在前面加上*号取这个地址上的值。 **
例如:遍历整个链表并输出值
for(list<int>::iterator it = lis.begin();it != lis.end(); i++){
cout<<*(it)<<' ';
}
4. 迭代器的实质
我们通过上面的了解知道了要想获取某一个节点的在值有两个方式
1.获取前一个节点的next指针
2.获取后一个节点的pre指针
迭代器便是第一种方式
注意:在开头创建并赋值的迭代器该值并不是固定指向链表的头的,而是会跟随后面的增加而增加的
怎么说呢,我尝试过想去看源码,但是尝试看了一下,C++源码真的让人头大。。。
这时候还要再仔细说一下链表的结构
链表创建的时候,头尾指针指向一个地址
插入第一个数据的时候head跳转到第一个数据,始终指向第一个,tali依旧指向原本的地址:
插入第二个数据的时候,head始终不变,除非插入head。而要插入到后面,就是要替换tail的位置,tail就会被顶到后面去。
同理,如果it是在一个数据都没有的时候创建的当时head与tail指向同一个地址,而head在变,迭代器it的地址不会变
这时候迭代器的实质就非常清晰了,迭代器就是一个指针,代表一个地址!
这时候解释开头定义的迭代器为什么不是一直在开头的就非常容易理解了。当因为当时创建的时候是指向开头的,但是随着数据的插入这个迭代器在链表中的位置一直被顶下去。
而如果一直使用一个迭代器插入的话就相当于在前面插入的后面,这个迭代器的前面。就会一直排在前面插入的后面,类似push_back()的效果!
!!! 链表的插入理解为将原来的位置顶到后面去就非常好理解了!!!!
而如果一直使用一个迭代器插入的话就相当于在前面插入的后面,这个迭代器的前面。就会一直排在前面插入的后面,类似push_back()的效果!
!!! 链表的插入理解为将原来的位置顶到后面去就非常好理解了!!!!