- 单链表的存储示意图
- 对于结点类的描述
package LinkList;
//对于结点的描述
public class Node {
public Object data; //存放结点值
public Node next; //后继结点的引用
//无参数时的构造函数
public Node(){
this(null,null);
}
//带一个参数的构造函数
public Node(Object data){
this(data,null);
}
//带两个参数的构造函数
public Node(Object data,Node next){
this.data=data;
this.next=next;
}
}
- 单链表类的描述
public Node head; //单链表的头指针
public LinkList(){ //单链表的构造函数
head = new Node(); //初始化头结点
}
public LinkList(int n ,boolean Order) throws Exception{ //构造一个长度为N的单链表
this(); //初始化头结点
if(Order){ //用尾插法顺序建立单链表
create1(n);
}
else{
create2(n); //用头插法逆位序建立单链表
}
}
- 用头插法逆位建立单链表,其中n为单链表的结点个数
//用头插法逆序建立单链表,其中n为单链表的结点个数
public void create1(int n) throws Exception{
Scanner sc =new Scanner(System.in);
for(int j =0;j<n;j++){
insert(0,sc.next());
}
}
- 用尾插法顺序建立单链表,其中n为单链表的结点个数
//用尾插法顺序建立单链表,其中n为单链表的结点个数
public void create2(int n) throws Exception{
Scanner sc = new Scanner(System.in);
for(int j = 0 ;j<n;j++){
insert(length(),sc.next());
}
}
- 将一个已经存在的带头结点单链表置成空表
//将一个已经存在的带头结点单链表置成空表
public void clear(){
head.data=null;
head.next=null;
}
- 判断带头结点的单链表是否为空
//判断带头结点的单链表是否为空
public boolean isEmpty(){
return head.next==null;
}
- 求带头结点的单链表的长度
//求带头结点的单链表的长度
public int length(){
Node p = head.next; //初始化,p指向首结点,length为计数器
int length=0;
while (p!=null){ //从首结点开始向后查找,直到p为空
p=p.next; //指向后继结点
length++; //长度增加1
}
return length;
}
- 读取带头结点的单链表中的第i个结点
//读取带头结点的单链表中的第i个结点
public Object get(int i ) throws Exception{
Node p = head.next; //初始化,p指向首结点,j为计数器
int j = 0 ;
while (p!=null && j<i){ //从首结点开始向后查找,直到p指向第i个结点或者p为空
p = p.next; //指向后继结点
++j; //计数器的值增1
}
if (p==null || j>i) //i小于0或者大于表长减一时,即i不合法
throw new Exception("第"+i+"个元素不存在"); //抛出异常
else
return p.data;//返回结点p的数值域值
}
不能将变量初始化为’p=head;j=-1’,因为当输入i=-1时,j=i,会输出,但此时i是非法的
- 在带头结点的单链表中查找值为x的结点
//在带头结点的单链表中查找值为x的结点
public int indexOf(Object x){
Node p = head.next;
int j =0;
//下面从单链表中的首结点开始查找,直到p.data为x或到达单链表的表尾
while (p!=null&& !p.data.equals(x)){
p = p.next; //指向下一个结点
++j; //计数器的值增加1
}
if(p!=null)
return j;
else
return -1;
}
- 输出单链表中的所有节点
//输出单链表中的所有结点
public void display(){
Node node = head.next; //获取带头结点的单链表的首结点
while (node!= null){
System.out.print(node.data+""); //输出结点的值
node = node.next; //取下一个结点
}
System.out.println(); //换行
}
- 在带头结点的单链表中的第i个结点之前插入一个值为x的新结点
不能,因为可能需要在首结点后或者头结点前插入结点
//在带头结点的单链表中的第i个结点之前插入一个值为x的新结点
public void insert(int i,Object x) throws Exception{
Node p = head; //初始化p为头结点,j为计数器
int j = -1;
while (p!=null && j<i-1){ //寻找第i个结点的前驱,即第i-1个结点
p = p.next;
++j;
}
if (j>i-1 || p ==null){ //i不合法
throw new Exception("插入位置不合法"); //抛出异常
}
Node s = new Node(x); //生成新结点
s.next=p.next; //修改链,使新结点插入单链表中
p.next=s;
}
- 在不带头结点的单链表中的第i个结点之前插入一个值为x的新结点
不带头结点的单链表,新结点要插入到不带头结点的单链表的表头,需要将新结点s的后继指针指向原来单链表的第一个结点,并将头指针指向新结点,使新结点成为插入后的单链表中的第一个结点
//在不带头结点的单链表中的第i个结点之前插入一个值为x的新结点
//在不带头结点的单链表中的第i个结点之前插入一个值为x的新结点
public void insert2(int i,Object x) throws Exception{
Node p = head; //初始化p为头结点,j为计数器
int j = 0;
while (p!=null && j<i-1){ //寻找第i个结点的前驱,即第i-1个结点
p = p.next;
++j;
}
if (j>i-1 || p ==null){ //i不合法
throw new Exception("插入位置不合法"); //抛出异常
}
Node s = new Node(x); //生成新结点
if(i==0){ //在表头位置插入一个新的结点
s.next=p.next;
head=s;
}
else{
s.next=p.next; //修改链,使新结点插入单链表中
p.next=s;
}
}
- 删除带头结点的单链表中的第i个结点
//删除带头结点的单链表中的第i个结点
public void remove(int i) throws Exception{
Node p =head; //初始化p指向头结点,j为计数器
int j = -1;
while (p.next!=null && j<i-1){ //寻找第i个结点的前驱
p = p.next;
++j;
}
if (j>i-1 || p.next ==null){
throw new Exception("删除位置不合法"); //抛出异常
}
p.next= p.next.next; //修改链指针,使待删结点从单链表中脱离出来
}
- 删除不带头结点的单链表中的第i个结点
在不带头结点的单链表上删除第i个结点,则也要像插入操作一样分成两种情况分别处理,一种情况是删除第一个结点,另一种情况是删除其他位置上的结点
//删除不带头结点的单链表中的第i个结点
public void remove1(int i) throws Exception{
Node p =head; //初始化p指向头结点,j为计数器
int j = 0;
while (p.next!=null && j<i-1){ //寻找第i个结点的前驱
p = p.next;
++j;
}
if (j>i-1 || p.next ==null){
throw new Exception("删除位置不合法"); //抛出异常
}
if(i==0){
head=p.next.next;
}
else{
p.next= p.next.next; //修改链指针,使待删结点从单链表中脱离出来
}
}
- 在带头结点的单链表上删除数据域值为x的结点
//在带头结点的单链表上删除数据域值为x的结点
public void remove2(int i) throws Exception{
Node p =head; //初始化p指向头结点
while (p.next!=null && p.next.data!=x){ //沿着链依次查找数据域值为x的结点
p = p.next;
}
if (p.next ==null){
throw new Exception("删除位置不合法"); //抛出异常
}
p.next= p.next.next; //修改链指针,使待删结点从单链表中脱离出来
}
- 在做删除和插入操作时,可以令i=0/1/-1去测试