先说一下线性表。
线性表:在逻辑上,数据是连续的。线性表有两种存储方式:顺序存储方式和链式存储方式。
数组(array):数组就是线性表的顺序存储方式。数组的内存是连续分配的,并且是静态分配的,即在使用数组之前需要分配固定大小的空间。
链表(linked-list):链表就是线性表的链式存储方式。链表的内存是不连续的,前一个元素存储地址的下一个地址中存储的不一定是下一个元素。链表通过一个指向下一个元素地址的引用将链表中的元素串起来。
链表分为单链表,双向链表和循环链表。在这里只写了单向链表的各种操作。
单链表的实现
public class ListNode {
int val;
ListNode next;
ListNode( int x ) { this.val = x; };
}
- 后插法:
public ListNode insert(ListNode head,int value) {
ListNode t = new ListNode(value);
t.next = head;
return t;
}
- 反转链表
public ListNode reverseLinkedList(ListNode head) {
ListNode ReverseHead = null;
ListNode t = null;
while ( head!=null ) {
t = head.next;
head.next = ReverseHead;
ReverseHead = head;
head = t;
}
return ReverseHead;
}
- 获取中间结点
public ListNode getMiddle(ListNode head) {
if ( head==null || head.next==null ) return head;
ListNode slow = head,fast = head;
while( fast.next!=null && fast.next.next!=null ) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
- 获取倒数第k个结点
public ListNode findLastK( ListNode head,int k) {
ListNode p1 = head;
ListNode p2 = head;
for ( int i=0; i<k; i++ ) {
if ( p2==null ) {
return null;
}
p2 = p2.next;
}
while ( p2!=null ) {
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
- 判断是否有环
public boolean isLoop(ListNode head) {
boolean flag = false;
ListNode slow = head,
fast = head;
while ( fast!=null && fast.next!=null ) {
fast = fast.next;
slow = slow.next;
if ( slow==fast ) {
flag = true;
break;
}
}
return flag;
}
- 寻找环的起点
public ListNode finsLoopStart( ListNode head ) {
ListNode slow = head,
fast = head;
while ( fast!=null && fast.next!=null ) {
fast = fast.next.next;
slow = slow.next;
if ( fast==slow ) break;
}
if ( fast==null || fast.next==null )
return null;
else {
slow = head;
while ( slow!=fast ) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
7.删除重复结点
public void deleteListNode ( ListNode head ) {
ListNode p = head,
q = null;
while ( p!=null ) {
q = p.next;
while ( q!=null && q.val==p.val ) {
q = q.next;
}
p.next = q;
p = p.next;
}
}