链表
- 一、线性结构和非线性结构
- 1、非线性结构
- 2、线性结构
- 2.1顺序表
- 2.2链表
- 二、链表
- 1、单链表
- 1.1、代码实现
- 1.2、单链表的反转
一、线性结构和非线性结构
- 在说链表之前我们先了解一下线性结构和非线性结构
1、非线性结构
- 其逻辑特征是一个结点元素可能有多个直接前趋和多个直接后继,也就是说其特点是数据元素之间关系是一对多、多对一等,常见的非线性结构有:二维数组,多维数组,广义表,树(二叉树等)。
2、线性结构
- 线性结构有两种不同的存储结构,即顺序存储结构和链式存储结构,顺序存储的线性表称为顺序表(如图3a),链式存储的线性表称为链表(如图3b)。
- 线性结构常见的有:数组、队列、链表和栈。
2.1顺序表
- 顺序表中的存储元素是连续的
2.2链表
- 链表中的存储元素不一定是连续的,元素节点中存放数据元素以及相邻元素的地址信息。
二、链表
1、单链表
- 先上张图,方便我们进行理解
- 如图所示:
- 我们的头指针指向了地址为150的节点
- 地址150节点data存放了a1,next指向了地址为110的节点
- 以此类推,直到next指向空
- 结论:
- 链表是以节点的方式来存储,是链式存储
- 每个节点包含 data 域, next 域:指向下一个节点.
- 发现链表的各个节点不一定是连续存储.
- 链表分带头节点的链表和没有头节点的链表,根据实际的需求来确定
1.1、代码实现
- 添加:代码使用尾部插入方法。
- 插入:通过编号对插入节点进行排序。
- 删除:当前节点的next指向下下个节点
- 修改:通过编号查询到节点进行修改
- 代码实现
class SingleLinkedList{
//初始化头节点
private HeroNode heroNode = new HeroNode(0,"","");
//链表结尾添加节点
public void addNode(HeroNode heroNode ){
HeroNode temp = this.heroNode;
while (true){
if (temp.next==null){
break;
}
temp = temp.next;
}
temp.next = heroNode;
}
//删除节点
public void delNode(int no){
HeroNode temp = this.heroNode;
boolean flag = false;
if (temp.next == null){
System.out.println("链表为空");
}
while (true){
if (temp.next.no == no){
flag = true;
break;
}
if(temp.next == null){
break;
}
temp = temp.next;
}
if (flag){
temp.next = temp.next.next;
}else {
System.out.println("没有找到该编号");
}
}
//修改节点数据
public void updateNode(HeroNode heroNode){
HeroNode temp = this.heroNode;
boolean flag = false;
if (temp.next == null){
System.out.println("链表为空");
}
while (true){
if (temp.no == heroNode.no){
flag = true;
break;
}
if(temp.next == null){
break;
}
temp = temp.next;
}
if (flag){
temp.no = heroNode.no;
temp.name = heroNode.name;
temp.nickname = heroNode.nickname;
}else {
System.out.println("没有找到该节点");
}
}
//添加节点进行编号排序
public void orderByAddNode(HeroNode heroNode ){
HeroNode temp = this.heroNode;
boolean flag=false;
while (true){
if (temp.next ==null){
break;
}
if (temp.next.no == heroNode.no){
flag = true;
break;
}
if (temp.next.no> heroNode.no){
break;
}
temp = temp.next;
}
if (flag){
System.out.println("编号存在");
}else {
heroNode.next = temp.next;
temp.next = heroNode;
}
}
//打印
public void list(){
HeroNode temp = this.heroNode.next;
while (true){
System.out.println(temp);
if (temp.next==null){
break;
}
temp = temp.next;
}
}
}
//一个HeroNode为一个节点
class HeroNode{
public int no;
public String name;
public String nickname;
public HeroNode next;
HeroNode (int no,String name,String nickname){
this.no=no;
this.name=name;
this.nickname=nickname;
}
@Override
public String toString() {
return "Heronode{" +
"no='" + no + '\'' +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
1.2、单链表的反转
- 方法一:过于麻烦
//链表翻转
public void reversalNode(){
HeroNode temp = heroNode.next;
HeroNode next = null;
HeroNode reversalNode = new HeroNode(0,"","");
//链表为空,无需反转直接返回
if (temp == null){
System.out.println("链表为空");
return;
}
while (temp!=null){
//记录节点的下一个节点
next = temp.next;
//当前节点指向reversalNode下一个节点也就是除去头节点的reversalNode
temp.next = reversalNode.next;
//reversalNode头结点再指向temp
reversalNode.next = temp;
//temp继续引用next进入下一个节点进行反转
temp = next;
}
heroNode = reversalNode;
}
- 方法二:利用栈先进后出的特点进行反转
public void stackList( ){
Stack<HeroNode> heroNodes = new Stack<>();
if (heroNode.next==null){
return;
}
HeroNode temp = this.heroNode;
while (true){
if (temp.next==null){
break;
}
heroNodes.push(temp.next);
temp = temp.next;
}
while (heroNodes.size()>0){
System.out.println(heroNodes.pop());
}
}
后续会对双向链表以及栈进行说明!
如有错误请指出!谢谢