分析:
先要满足以下基本的要求,遇到问题再做完善。
单链表的属性
结点类:
数据项 data
结点类型的变量 next
单链表类:
结点类型的变量 head
单链表类要实现的方法
判断链表是否为空
清空链表
求链表长度
遍历链表并输出
插入(头插,尾插,索引位置插)
删除(头删,尾删,索引位置删)
查找(给定元素索引,给定索引元素)
更改(更改指定索引位置为元素值)
注意事项
1.结点类型的成员变量head永远是头节点的引用,所以不要直接对head进行操作,通过Node temp = head,对临时变量temp进行操作,不会影响到head;
2.因将链表长度存储在了头节点的数据项,所以在对链表中元素个数产生影响的方法要及时调整head.data的值。
属性设置
//结点类属性
int data;//数据项
Node next;//后继结点
public Node(int data) {//仅能通过此构造方法生成结点对象
this.data = data;
}
//单链表类属性
Node head = new Node(0);//初始化头节点,并用头节点的数据项存储单链表长度
方法实现
1.判断链表是否为空:
两种方法:
头节点的next’属性为null则为空
头节点的数据项data为0则为空
public boolean isEmpty(){//判空
if(head.next == null)
return true;
return false;
}
public boolean isEmpty1(){
if(head.data == 0)
return true;
return false;
}
2.清空链表:
头节点的数据项data设为0,后继结点next设为null
public void clear(){//清空
head.next = null;
head.data = 0;
}
3.长度:
返回头节点的数据项data即可
public int getLength(){//返回单链表长度
return head.data;
}
4.遍历:
通过使用结点的后继结点next属性来一直后移即可。
图解:
public void travers(){//遍历
if(head.next == null){
System.out.println("当前单链表为空");
return;
}
Node temp = head;
System.out.print("[");
while(temp.next != null){
temp = temp.next;
if(temp.next == null){
System.out.println(temp.data + "]");
}else{
System.out.print(temp.data + ",");
}
}
}
5.插入:(头插)
图解:
public void insertHead(int value){//头插
Node node = new Node(value);
node.next = head.next;
head.next = node;
head.data++;
}
6.插入(尾插):
图解:
public void insertEnd(int value){//尾插
Node node = new Node(value);
Node temp = head;
while(temp.next != null){
temp = temp.next;
}
temp.next = node;
head.data++;
}
7.插入(索引位置插入):
temp移动到索引位置的前一项,然后执行类似于5中头插法的操作即可。图解:
public void insert(int index,int value){//索引位置插
if(index < 1 || index > head.data+1){
System.out.println("索引值不合法!");
return;
}
Node node = new Node(value);
Node temp = head;
for(int i = 0;i < index - 1;i++){
temp = temp.next;
}
node.next = temp.next;
temp.next = node;
head.data++;
}
8.删除(头删):
head.next指向haed.next.next即可
temp图解:
public void deleteHead(){//删头
if(head.data == 0){
System.out.println("空链表!无法再执行删除!");
return;
}
head.next = head.next.next;
head.data--;
}
9.删除(尾删):
temp移动到尾部元素的直接前驱,然后temp.next指向null即可(后移次数用head.data控制,移动head.data-1次后,temp指向末尾的直接前驱,即倒数第二个元素)
图解:
10.删除(删除索引位置元素):
temp移动到指定索引位置的直接前驱,通过,用给定的索引值index控制移动次数,移动index-1次,然后通过temp.next = temp.next.next;来删除索引位置元素。
图解:
public void deleteEnd(){//删尾
if(head.data == 0){
System.out.println("空链表!无法再执行删除!");
return;
}
Node temp = head;
for(int i = 0 ;i < head.data - 1;i++){
temp = temp.next;
}
temp.next = null;
head.data--;
}
11.查找(指定元素求索引):
与4中遍历的操作一致,在遍历每个结点时插入比较temp.data == value;为true则return 遍历过的结点数;为false:继续遍历,直到找到或者temp.next == null,遍历完还未找到即return -1;
public int locateElement(int value){//定位指定元素索引(首次出现 不存在返回-1
Node temp = head;
for(int i = 0;i < head.data;i++){
temp = temp.next;
if(temp.data == value){
return i+1;
}
}
return -1;
}
12.查找:(指定索引元素)
同上,通过temp=temp.next后移,用给定的索引值index值控制移动次数,因为要到index处的结点,所以移动index次,移动完成后,通过return temp.data;返回该结点的数据项;
public int getElement(int index){//返回指定索引值元素 索引非法返回-1
if(index < 1 || index > head.data){
return -1;
}
Node temp = head;
for(int i = 0;i < index;i++){
temp = temp.next;
}
return temp.data;
}
13.更改(更改指定索引位置元素值):
同上,遍历到索引为index处的结点,通过temp.data = value;更改索引位置的元素值;
public void update(int index,int value){//更改指定索引位置的元素值
if(index < 1 || index > head.data){
System.out.println("索引值非法");
}
Node temp = head;
for(int i = 0;i < index;i++){
temp = temp.next;
}
temp.data = value;
}
综上,带头结点的单链表基本实现。