目录
1.如何实现单链表的增删操作
链表是一种递归的数据结构,它或者为空(null),或者指向一个节点的引用,该节点含有一个泛型的元素和一个指向另一条链表的引用。
以下给出链表的基本操作:
public class Node {
int data;
Node next = null;
public Node(int data){
this.data=data;
}
}
public class MyLinkedList {
Node head = null; //链表头的引用
//向链表末尾中插入数据
public void addNode(int d){
Node newNode = new Node(d);
if(head==null){
head=newNode;
return;
}
Node tmp = head;
while(tmp.next!=null){
tmp=tmp.next;
}
tmp.next=newNode;
}
//删除第chs个节点
public Boolean deleteNode(int chs){
if(chs<1||chs>length()){
return false;
}
//删除链表第一个元素
if(chs==1){
head=head.next;
return true;
}
int i=2;
Node preNode = head;
Node curNode = preNode.next;
while(curNode!=null){
if(i==chs){
preNode.next=curNode.next;
return true;
}
preNode=curNode;
curNode=curNode.next;
i++;
}
return true;
}
//返回节点长度
public int length(){
int length = 0;
Node temp = head;
while(temp!=null){
length++;
temp=temp.next;
}
return length;
}
//对链表进行排序,返回头节点
public Node orderList(){
Node nextNode = null;
int temp=0;
Node curNode=head;
while(curNode!=null){
nextNode=curNode.next;
while(nextNode!=null){
if(curNode.data>nextNode.data){
temp=curNode.data;
curNode.data=nextNode.data;
nextNode.data=temp;
}
nextNode=nextNode.next;
}
curNode=curNode.next;
}
return head;
}
public void printList(){
Node tmp = head;
while(tmp!=null){
System.out.print(tmp.data+" ");
tmp=tmp.next;
}
System.out.println();
}
public static void main(String[] args) {
MyLinkedList list = new MyLinkedList();
list.addNode(5);
list.addNode(9);
list.addNode(2);
list.addNode(7);
System.out.println("listLen= "+list.length());
System.out.println("before order: ");
list.printList();
list.orderList();
System.out.println("after order: ");
list.printList();
}
}
结果:
2.如何从链表中删除重复数据
最容易想到的就是遍历链表,把遍历到的值存放到一个Hashtable中,在遍历时,若已存在,则说明数据重复,可以删除。
import java.util.Hashtable;
public class DeleteDupNode {
public static void deleteDuplecate(Node head){
Hashtable<Integer,Integer> table = new Hashtable<>();
Node tmp = head;
Node pre = null;
while(tmp!=null){
if(table.containsKey(tmp.data))
pre.next=tmp.next;
else{
table.put(tmp.data,1);
pre=tmp;
}
tmp=tmp.next;
}
}
public static void main(String[] args) {
Node a = new Node(1);
Node b = new Node(1);
Node c = new Node(2);
Node d = new Node(2);
Node e = new Node(3);
a.next=b;
b.next=c;
c.next=d;
d.next=e;
e.next=null;
Node tmp=a;
while(tmp!=null){
System.out.print(tmp.data+" ");
tmp=tmp.next;
}
tmp=a;
System.out.println();
deleteDuplecate(a);
while(tmp!=null){
System.out.print(tmp.data+" ");
tmp=tmp.next;
}
}
}
结果:
这种方法事件复杂度较低,但也有明显缺点,就是在遍历时需要额外的存储空间来保存已遍历过的值。
还有一种方法不需要额外存储空间,主要思路为对链表进行双重循环遍历,外循环正常遍历链表,假设外循环当前遍历节点为cur,内循环从cur开始遍历,若碰到与cur所指向结点值相同,则删除这个重复结点。这个方法时间复杂度比上面那个高。
public void deleteDuplecate(Node head){
Node p= head;
while(p!=null){
Node q=p;
while(q.next!=null){
if(p.data==q.next.data){
q.next=q.next.next;
}else
q=q.next;
}
p=p.next;
}
}
3.如何找出单链表中倒数第k个元素
假设带头节点的单链表,设置两个指针,一个先前移k步,然后两个指针同时往前移动,循环直到先行地指针值为null,另一个指针所指位置就是要找的位置。
public class FindKElem {
public static Node findElem(Node head,int k){
if(k<1){
System.out.println("k不能小于1");
return null;
}
Node p1=head;
Node p2=head;
for(int i = 0 ; i < k; i++)
p1=p1.next;
if(p1==null){
System.out.println("k不合法");
return null;
}
while(p1!=null){
p1=p1.next;
p2=p2.next;
}
return p2;
}
public static void main(String[] args) {
Node chs=new Node();
Node a = new Node(1);
Node b = new Node(2);
Node c = new Node(3);
Node d = new Node(4);
Node e = new Node(5);
chs.next=a;
a.next = b;
b.next = c;
c.next = d;
d.next = e;
e.next = null;
System.out.println(findElem(chs, 5).data);
}
}
结果: 1
4.如何反向输出单链表
public class ReverseNode {
public static Node ReverseIteratively(Node head){
Node ReverseHead = head;
Node p = head;
Node pre = null;
while(p != null){
Node q = p.next;
if(q==null)
ReverseHead = p;
p.next = pre;
pre = p;
p = q;
}
head = ReverseHead;
return head;
}
public static void main(String[] args) {
Node a = new Node(1);
Node b = new Node(2);
Node c = new Node(3);
Node d = new Node(4);
Node e = new Node(5);
a.next = b;
b.next = c;
c.next = d;
d.next = e;
e.next = null;
Node tmp=a;
System.out.println("反转之前:");
while(tmp!=null){
System.out.print(tmp.data+" ");
tmp=tmp.next;
}
System.out.println();
Node chs = ReverseIteratively(a);
System.out.println("反转之后:");
while(chs!=null){
System.out.print(chs.data+" ");
chs=chs.next;
}
}
}
结果: