单链表
是一个有序的列表,前一个节点存在后一节点的地址信息的链式结构。
小结:
-
链表是以节点的方式来存储,是链式存储
-
每个节点包含 data 域, next 域:指向下一个节点.
-
如图:发现链表的各个节点不一定是连续存储.
-
链表分带头节点的链表和没有头节点的链表,根据实际的需求来确定。
链表逻辑结构示意图:
public class SingleLinkedListDemo {
public static void main(String[] args) {
SingleLinkedList singleLinkedList = new SingleLinkedList();
singleLinkedList.addByOrder(new HeroNode(7,"林冲","豹子头"));
System.out.println("打印");
singleLinkedList.show();
singleLinkedList.addByOrder(new HeroNode(2,"周杰伦","zjj"));
singleLinkedList.addByOrder(new HeroNode(5,"林俊杰","ljj"));
System.out.println("打印");
singleLinkedList.show();
singleLinkedList.addByOrder(new HeroNode(8,"李宗盛","鬼才"));
System.out.println("打印");
singleLinkedList.show();
//// singleLinkedList.update(new HeroNode(8,"李宗盛 new","鬼才 new"));
//// System.out.println("打印");
//// singleLinkedList.show();
// singleLinkedList.delete(2);
// singleLinkedList.delete(8);
// System.out.println("删除后");
// singleLinkedList.show();
//求单链表节点个数
// System.out.println("节点个数:"+singleLinkedList.getNodeSize());
// System.out.println("倒数第二个节点:"+singleLinkedList.findLastIndexNode(2));
// System.out.println("反转");
// singleLinkedList.reversetList();
// singleLinkedList.show();
singleLinkedList.reverPrint();
}
}
//定义一个SingleLinkedList
class SingleLinkedList{
//先定义一个头结点
private HeroNode header=new HeroNode(0,"","");
//添加到最后
public void addTail(HeroNode node){
//从头结点开始,找到最后一个节点(next=null)
HeroNode temp=header;
while(true){
if(temp.next==null){
break;
}
//后移
temp=temp.next;
}
//跳出循环说明找到最后一个元素
temp.next=node;
}
//根据no进行添加 不能重复添加
public void addByOrder(HeroNode node){
//从头节点开始
HeroNode temp=header;
while (true){
if(temp.next==null){
break;
}
//需找到添加位置的前一个节点
if(node.no<temp.next.no){
break;
}
if(node.no==temp.next.no){
throw new RuntimeException("【"+node.no+"】已经存在");
}
temp=temp.next;
}
//此时符合添加条件
HeroNode heroNode=temp.next;
temp.next=node;
node.next=heroNode;
}
//根据no进行修改
public void update(HeroNode node){
if(header.next==null){
throw new RuntimeException("链表为空");
}
boolean update=false;
HeroNode temp=header.next;
while (true){
if(temp==null){
break;
}
if(temp.no==node.no){
update=true;
temp.name=node.name;
temp.nickName=node.nickName;
break;
}
temp=temp.next;
}
if(!update){
System.out.println("更新失败,没有找到【"+node.no+"】元素");
}
}
//根据no进行删除
public void delete(int no){
HeroNode temp=header;
boolean delete=false;
while (true){
if(temp.next==null){
break;
}
//找到这个元素前一个节点
if(temp.next.no==no){
delete=true;
temp.next=temp.next.next;
break;
}
temp=temp.next;
}
if(!delete){
throw new RuntimeException("删除失败,没有找到【"+no+"】元素");
}
}
//显示链表
public void show(){
if(header.next==null){
System.out.println("链表为空");
return;
}
//从头结点开始
HeroNode temp=header;
while (true){
if (temp.next!=null){
System.out.println(temp.next);
temp=temp.next;
}else {
break;
}
}
}
//单链表节点个数
public int getNodeSize(){
HeroNode temp=header.next;
int count=0;
while (true){
if(temp==null){
break;
}
count++;
temp=temp.next;
}
return count;
}
//查找单链表倒数第K个节点 得到size 遍历到size-index即可
public HeroNode findLastIndexNode(int index){
int size=getNodeSize();
if(index<=0||index>size){
throw new RuntimeException("索引不符合规则");
}
int n=size-index; //逆序转正序
int count=0;
HeroNode temp=header.next;
while (true){
if(temp==null){
break;
}
if(count==n){
break;
}
temp=temp.next;
count++;
}
return temp;
}
//将单链表实现反转
public void reversetList(){
//没有或者只有一个节点
if(header.next==null||header.next.next==null){
return ;
}
//新建一个反转节点
HeroNode reverHeader = new HeroNode(-1, "", "");
HeroNode cur=header.next;
HeroNode next=null;
//遍历原来的节点
while (true){
if(cur==null){
break;
}
//每遍历一个节点就放入reverHeader的最前端 把之前那个元素指向当前下一个
next=cur.next;
cur.next=reverHeader.next;//每次指向最前一个
reverHeader.next=cur;
//继续遍历
cur=next;
}
//最后将header指向reverheader.next
header.next=reverHeader.next;
}
public void reverPrint(){
if(header.next==null){
return;
}
HeroNode temp=header.next;
Stack<HeroNode> stack=new Stack<HeroNode>();
while (true){
if(temp==null){
break;
}
stack.push(temp);
temp=temp.next;
}
System.out.println("----反向输出---");
while (stack.size()>0){
System.out.println(stack.pop());
}
}
}
//定义一个英雄节点
class HeroNode{
public int no;
public String name;
public String nickName;
public HeroNode next;
public 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 + '''+
'}';
}
}
双向链表
单向链表的缺点分析:
单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。
单向链表不能自我删除,需要靠辅助节点 ,而双向链表,则可以自我删除,所以前面我们单链表删除时节点,总是找到temp,temp是待删除节点的前一个节点。
public class DoubleLinkedListDemo {
public static void main(String[] args) {
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
doubleLinkedList.add(new HeroNode2(1,"张三","zs"));
doubleLinkedList.add(new HeroNode2(2,"李四","ls"));
doubleLinkedList.add(new HeroNode2(3,"王五","ww"));
doubleLinkedList.add(new HeroNode2(4,"赵六","zl"));
doubleLinkedList.add(new HeroNode2(5,"宋七","sq"));
doubleLinkedList.display();
//// doubleLinkedList.delete(1);
//
// doubleLinkedList.update(new HeroNode2(5,"宋七 new","sq new"));
//
// doubleLinkedList.delete(8);
doubleLinkedList.add(2,new HeroNode2(7,"宋七1","sq1") );
doubleLinkedList.display();
}
}
class DoubleLinkedList{
HeroNode2 header=new HeroNode2(0,"","");
//返回头节点
public HeroNode2 getHeader(){
return header;
}
//遍历
public void display(){
System.out.println("-------显示-------");
HeroNode2 cur=header.next;
if(cur==null){
System.out.println("链表为空");
}
while (true){
if(cur==null){
break;
}
System.out.println(cur);
cur=cur.next;
}
}
//添加
public void add(HeroNode2 node){
HeroNode2 cur=header;
//找到最后一个元素加上
while (true){
if(cur.next==null){
break;
}
cur=cur.next;
}
cur.next=node;
node.pre=cur;
}
//根据no 添加
public void add(int no,HeroNode2 node){
HeroNode2 cur=header.next;
int count=1;
//找到最后一个元素加上
while (true){
if(count==no){
break;
}
count++;
cur=cur.next;
}
cur.pre.next=node;
node.next=cur;
node.pre=cur.pre;
cur.pre=node;
}
//根据no进行修改
public void update(HeroNode2 node){
if(header.next==null){
throw new RuntimeException("链表为空");
}
boolean update=false;
HeroNode2 temp=header.next;
while (true){
if(temp==null){
break;
}
if(temp.no==node.no){
update=true;
temp.name=node.name;
temp.nickName=node.nickName;
break;
}
temp=temp.next;
}
if(!update){
System.out.println("更新失败,没有找到【"+node.no+"】元素");
}
}
//根据no删除一个节点
public void delete(int no){
if(header.next==null){
throw new RuntimeException("链表为空");
}
boolean delete=false;
HeroNode2 temp=header.next;
while (true){
if(temp==null){
break;
}
if(temp.no==no){
//删除就是改变指向
temp.pre.next=temp.next;
//如果最后一个节点不需要执行
if(temp.next!=null){
temp.next.pre=temp.pre;
}
delete=true;
break;
}
temp=temp.next;
}
if(!delete){
System.out.println("删除失败,没有找到【"+no+"】元素");
}
}
}
//定义一个节点
class HeroNode2 {
public int no;
public String name;
public String nickName;
public HeroNode2 pre;
public HeroNode2 next;
public HeroNode2(int no, String name, String nickName) {
this.no = no;
this.name = name;
this.nickName = nickName;
}
@Override
public String toString() {
return "HeroNode2{" +
"no=" + no +
", name='" + name + ''' +
", nickName='" + nickName + ''' +
'}';
}
}