链表
1.以节点方式存储
2.每个节点包含data域,next域(指向下一个节点)
3.不是连续存储的
4.分为带头结点和没有头结点的链表
单链表
带头结点链表
注意其中的头结点是不会存放任何数据的
结点定义:
class Node{
int no;
String name;
String nickname;
Node next;//指向下一个结点
}
//可以重写toString方法便于输出
有了结点的定义之后,为了遍历查询方便,我们还需要定义一个包含结点链接关系的表。
class LinkList{
Node FisNode(0,"");//表示头指针,作为遍历链表查询的辅助工具
Node tem = FisNode;
public void add(Node n1) {//寻找链表结点中最后的结点
while(true) {
if(tem.next == null) {
break;//循环寻找该链表的末指针
}
tem = tem.next;
}
tem.next = n1;
}
}
单链表的初始化
class Node{
int no;
String name;
Node next;//指向该结点下一个结点的指针
public Node(int no,String name) {
this.name = name;
this.no = no;
this.next = null;
}
@Override
public String toString() {//重写方法,便于输出信息
return "Node [no=" + no + ", name=" + name + "]";
}
}
class NodeList{
Node FisNode = new Node(0,"");
//此为头指针,在查找时必须借助它来对它链接的数据进行查询
Node tem = FisNode;
public void add(Node n1) {
while(true) {
if(tem.next == null) {
break;//循环寻找该链表的末指针
}
tem = tem.next;
}
tem.next = n1;
}
//按照no顺序插入
public void addByorder(Node n1) {
tem = FisNode;//在有比较的情况下,需要保证每一次的比较都是重头开始的
while(true) {
if(tem.next == null) {//没有或者在当前链表最后
tem.next = n1;
break;
}
else if(tem.next.no > n1.no) {
n1.next = tem.next;
tem.next = n1;
break;
}
else if(tem.next.no == n1.no) {
System.out.println("equare.err");
break;
}
tem = tem.next;
}
}
public void delete(int no) {
tem = FisNode;
while(true) {
if(tem.next == null) {//没有或者在当前链表最后
break;
}
else if(tem.next.no == no) {
tem.next = tem.next.next;
break;
}
tem = tem.next;
}
if(tem.next == null) {
System.out.println("没有该no");
}
}
public void alter(int no,String name) {
tem = FisNode;
while(true) {
if(tem.next == null) {//没有或者在当前链表最后
break;
}
else if(tem.next.no == no) {
tem.next.name = name;
break;
}
tem = tem.next;
}
if(tem.next == null) {
System.out.println("没有该no");
}
}
}
单链表的反转
/单链表反转NodeList list,应该使用插入的方法,此方法最好写在外面,写在类里面会导致修改原NodeList中的值
public NodeList reverselist() {
NodeList list_new = new NodeList();
Node Fir_s = list_new.FisNode;//新链表的头指针
tem = FisNode.next;//指向链表头指针的下一个结点,第一个有值结点
Node next = new Node(1,"we");
while(tem != null) {
//下面四行是核心
next = tem.next;//记录要添加在新链表的结点的下一个结点位置,防止丢失链表
tem.next = Fir_s.next;//以插入的方式添加结点,插入位置为头结点后的第一个位置,所以其后续地址应该是原头结点的next地址
Fir_s.next = tem;//插入结点
tem = next;//tem指向的下一个要插入新链表中的结点,所以需要移动一位,指向保存了曾经结点位置next的结点
}
if(list_new.count()<1) {
System.out.println("err");
}
return list_new;
}
单链表反转思路:
1.反转即为 向一个新建的list中 将顺序遍历旧list得到的每一个结点插入到新列表头指针后面的一个位置
2.首先记录要插入结点的next,防止丢失旧链表
3.将该结点的next设为新链表头结点的next
4.插入结点
5.旧链表中指向结点的指针指向上一个结点的next位置,准备下一次的链表数据的添加
双向链表
每个结点既有指向下一个结点的next,也有指向上一个结点的pre。
仍然需要一个头结点作为辅助结点,帮助输出、删除等功能的实现
函数的大概写法和单链表都差不多,需要注意的点只有删除操作以及按序号插入时设置pre、next位置指向。
class dNodeList{
dNode FisNode = new dNode(0,"");
//此为头指针,同样作为辅助指针来帮助我们查找
dNode tem = FisNode;
public void add(dNode n1) {//数据插入到队尾
while(true) {
if(tem.next == null) {
break;//循环寻找该链表的末指针
}
tem = tem.next;
}
tem.next = n1;
n1.pre = tem;
}
public void list() {
tem = FisNode.next;
while(true) {
if(tem == null) {
break;
}
System.out.println(tem);
tem = tem.next;
}
}
public void addByorder(dNode n1) {
tem = FisNode;//在有比较的情况下,需要保证每一次的比较都是重头开始的
while(true) {
if(tem.next == null) {//没有或者在当前链表最后
tem.next = n1;
break;
}
else if(tem.next.no > n1.no) {
n1.next = tem.next;
n1.pre = tem;
tem.next.pre = n1;//注意顺序,不可以先将next设n1,这样会导致next.pre找不到原来的值
tem.next = n1;
break;
}
else if(tem.no == n1.no) {
System.out.println("equare.err");
break;
}
tem = tem.next;
}
}
public void delete(int no) {
tem = FisNode.next;
boolean flag = false;
while(true) {
if(tem == null) {//没有或者在当前链表最后
break;
}
else if(tem.no == no) {
flag = true;
break;
}
tem = tem.next;
}
if(flag) {
// System.out.println(true);
tem.pre.next = tem.next;
if(tem.next != null) {
tem.next.pre = tem.pre;
}
// System.out.println(true);
}
if(tem.next == null) {
System.out.println("没有该no");
}
}
public void alter(int no,String name) {
tem = FisNode;
while(true) {
if(tem.next == null) {//没有或者在当前链表最后
break;
}
else if(tem.next.no == no) {
tem.next.name = name;
break;
}
tem = tem.next;
}
if(tem.next == null) {
System.out.println("没有该no");
}
}
}