Java数据结构学习心得
前言
若有不足或错误之处,还请留言指出谢谢
提示:以下是本篇文章正文内容,下面案例可供参考
一、链表是什么?
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
----来自百度百科
二、单向链表
1.链表(LinkedList)在内存中的状态
小结:
1,链表是以节点的方式来存储(链式存储),每个节点都有自己在内存中的地址值
2,每个节点包含data域,next域。其中next域存在指针指向下一个节点。
3,如图,发现链表的各个节点不一定是连续存储。
4,链表分带头节点的链表和没有头结点的链表,头节点只有指针而不会存储数据,根据实际的需求来确定要不要头结点。
由上可知链表是有序的列表,但是它在内存中存储的方式是无序的。
最后一个节点的next域是null,代表这个链表结束了
2.单链表的创建
添加节点的示意图:
添加(创建)思路:
1,先创建一个head头节点,作用就是表示单链表的头
2,后面我们每添加一个节点,就直接加入到链表的最后
3,最后一个节点的next域的指针指向null,代表链表结束
定义一个HeroNode,每个HeroNode对象就是一个节点:
//可以用javaBean格式来封装
class HeroNode{
int no; //设置数据、属性1
String name; //设置数据、属性2
String nickName;//设置数据、属性3
HeroNode next; //next域 指向下一个节点
//有参构造,注意没有next域
public HeroNode(int no,String name,String nickName){
this.no=no;
this.name=name;
this.nickName=nickName;
}
}
定义一个SingleLinkedList 管理各个节点对象:
class SingleLinkesList {
//先初始化一个节点头,头节点不要动,不存放具体的数据
private HeroNode head = new HeroNode(0,"","");
// 添加节点到单向链表:
// 思路:当不考虑编号顺序时
//1.找到当前链表的最后节点
//2.将最后这个节点的next指向新的节点即可
public void add (HeroNode heroNode){
//因为head节点不能动,因此我们需要一个辅助节点 temp
HeroNode temp = head;
//遍历链表,找到最后
while(true){
//找到链表的最后
if(temp.next==null){
break;
}
//如果没有找到最后,就将temp后移
temp=temp.next;
}
//当退出while循环时,temp就指向了链表的最后
//那最后把他连上就可以了,让他等于新的节点
temp.next=heroNode;
}
//遍历输出
public void list(){
//判断链表是否为空
if(head.next==null){
System.out.println("链表为空");
return;
}
//因为头结点不能用,因此我们需要一个辅助变量来遍历
HeroNode temp = head.next;
while(true){
//判断链表是否到最后
if(temp==null){
break;
}
//输出节点信息
System.out.println(temp);
//将temp后移一位
temp=temp.next;
}
}
}
在节点1和节点2之间插入一个新节点(如图所示思路)
若需要按照编号的顺序来进行添加:
1,首先通过一个辅助变量(指针)temp,找到新添加的节点的位置(通过遍历)
2,让新节点的下一个域(.next)指向temp.next域
3,让temp.next指向新的节点
//第二种方式在添加节点的时候,根据排名将节点插入到指定位置
//如果有这个排名,则添加失败,并给出提示
public void addByOrder(HeroNode heroNode){
// 因为头结点不能动,因此需要一个辅助指针(变量)来帮助找到添加的位置
// 因为是单链表,因此temp是位于添加位置的前一个节点,否则插入不了
HeroNode temp = head;
boolean flag = false;//flag标志添加的编号是否已经存在,true为已经存在
while(true){
if (temp.next==null){//说明temp已经在链表的最后
break;
}
if (temp.next.no>heroNode.no){//说明位置已经找到,就在temp的后面插入
break;
}else if (temp.next.no==heroNode.no){//说明希望添加的heroNode的编号已经存在了
flag=true;//编号已存在标志
break;
}
temp=temp.next;//后移,继续向后遍历
}
//判断flag的值
if (flag){//不能添加,说明编号已经存在
System.out.printf("此节点编号%d已经存在,不能添加\n",heroNode.no);
}else {
//插入到链表中,左右相连: 1,先让(右连)新节点.next=temp.next 2,将(左连)temp.next=新节点
heroNode.next=temp.next;
temp.next=heroNode;
}
}
小结
以上代码模拟了单向链表在内存中的存储情况,通过添加节点模拟出了单向链表在内存中的增添元素的方式。虽然单向链表存储的实际情况是无序的,混乱的,但通过一条单链(next域)将各个元素相连,使其逻辑上变得有序,在其中添加元素也很方便。发散–>同时也可以通过这种方式将元素进行排序,即使集合在内存中就能实现排序,相比于在数据库中进行排序再将结果返回给服务器无疑速度快了许多。