鏈表
接口
public interface LinkedList<E>{
void addFirst(E e);
void add(int index,E e);
void removeFirst();
void remove(int index);
void remove(E e);
boolean contains(E e);
E get(int index);
void set(int index,E e);
boolean isEmpty();
Object[] toArray();
}
單向鏈表
public class SingleLinkedList<E> implements LinkedList<E> {
private class Node{
E e;
Node next;
public Node(E e) {
this.e = e;
}
public Node(E e, Node next) {
this.e = e;
this.next = next;
}
}
private Node dummyHead;
private int size;
public SingleLinkedList(){
dummyHead=new Node(null,null);
}
@Override
public void addFirst(E e) {
add(0,e);
}
@Override
public void add(int index, E e) {
//判斷下標是否越界,由於插入的位置可以是尾結點的後面,所以index可以爲size
if(index<0||index>size){
throw new IndexOutOfBoundsException("下標越界");
}
//獲取前驅結點
Node prev=prev(index);
//將結點插入
prev.next=new Node(e,prev.next);
size++;
}
private Node prev(int index){
//要找到一個節點的前驅結點,就要從頭結點的前驅結點開始找起。
Node temp=dummyHead;
for(int i=0;i<index;i++){
temp=temp.next;
}
return temp;
}
//刪除頭結點
@Override
public void removeFirst() {
remove(0);
}
@Override
public void remove(int index) {
checkIndex(index);
Node prev=prev(index);
Node curr=curr(index);
prev.next=curr.next;
curr=curr.next=null;
size--;
}
private Node curr(int index){
Node temp=dummyHead.next;
for(int i=0;i<index;i++){
temp=temp.next;
}
return temp;
}
@Override
public void remove(E e) {
Node prev=dummyHead;
Node curr=dummyHead.next;
while(curr!=null){
if(curr.e.equals(e)){
//找到和當前節點值相同的結點,將結點刪除
prev.next=curr.next;
curr=curr.next=null;
}
curr=curr.next;
prev=prev.next;
}
}
@Override
public boolean contains(E e) {
for (Node node=dummyHead.next;node!=null;node=node.next){
if(node.e.equals(e)){
return true;
}
}
return false;
}
@Override
public E get(int index) {
checkIndex(index);
return curr(index).e;
}
@Override
public void set(int index, E e) {
checkIndex(index);
Node curr=curr(index);
curr.e=e;
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public Object[] toArray() {
Object[] element=new Object[size];
int i=0;
for(Node node=dummyHead.next;node!=null;node= node.next){
element[i++]=node.e;
}
return element;
}
private void checkIndex(int index){
if(index<0||index>=size){
throw new IndexOutOfBoundsException("下標越界");
}
}
}
雙向鏈表
public class DoubleLinkedList<E> implements LinkedList<E> {
private class Node{
E e;
Node prev;
Node next;
public Node(E e) {
this.e = e;
}
}
private Node head;
private Node tail;
private int size;
@Override
public void addFirst(E e) {
add(0,e);
}
@Override
public void add(int index, E e) {
if(index<0||index>size){
throw new IndexOutOfBoundsException("下標越界");
}
Node curr = null;
if(index==size) {
//說明要插入位置當前沒有結點
curr = null;
}else {
//在curr()方法中尋找結點
curr=curr(index);
}
//創建新節點
Node node=new Node(e);
if(curr==null){
//當前量表長度爲0,說明當前鏈表沒有結點
if(size==0){
head=tail=new Node(e);
}else{
//當前要插入的結點要作爲鏈表的尾結點
tail.next=node;
node.prev=tail;
tail=node;
}
}else{
//找到當前節點覺得前驅結點
Node prev=curr.prev;
//如果當前節點爲空,頭插
if(curr==head){
node.next=head;
head.prev=node;
head=node;
}else{
node.next=prev.next;
prev.next=node;
node.prev=curr.prev;
curr.prev=node;
}
}
size++;
}
private Node curr(int index){
//由於是雙向鏈表,所以從頭結點和尾結點都可以訪問鏈表,所以可以判斷要找的index裏頭結點近還是尾結點近從而減少訪問次數
int t=size>>1;
if(index<t) {
Node temp = head;
for (int i = 0; i < index; i++) {
temp = temp.next;
}
return temp;
}else{
Node temp=tail;
for (int j=size-1;j>index;j--){
temp=temp.prev;
}
return temp;
}
}
@Override
public void removeFirst() {
remove(0);
}
@Override
public void remove(int index) {
checkIndex(index);
Node curr=curr(index);
Node prev=curr.prev;
Node next=curr.next;
if(curr==head){
//當前節點石頭結點,將頭結點向後移
head=head.next;
head.prev=null;
}else {
//當前節點不是頭結點
prev.next=curr.next;
curr.next=null;
}
if(curr==tail){
//當前節點是尾結點
tail=tail.prev;
tail.next=null;
}else {
next.prev=curr.prev;
curr.prev=null;
}
curr=curr.next=curr.prev=null;
size--;
}
private void checkIndex(int index){
if(index<0||index>=size){
throw new IndexOutOfBoundsException("下標越界");
}
}
@Override
public void removeNode(E e) {
//刪除所有值爲e的結點
Node first=head;
int index=0;
//當前節點不爲空
while(first!=null){
//將temp存入first的下一個結點
Node temp=first.next;
if(first.e.equals(e)){
//找到相同的結點通過索引的方式刪除,同時index不加1
remove(index);
}else {
//否則index向後走一步
index++;
}
first=temp;
}
}
@Override
public boolean contains(E e) {
for (Node temp=head;temp!=null;temp=temp.next){
if(temp.e.equals(e)){
return true;
}
}
return false;
}
@Override
public E get(int index) {
checkIndex(index);
return curr(index).e;
}
@Override
public void set(int index, E e) {
checkIndex(index);
Node curr=curr(index);
curr.e=e;
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public Object[] toArray() {
Object[] element=new Object[size];
int i=0;
for(Node node =head; node!=null; node= node.next){
element[i++]=node.e;
}
return element;
}
}
;
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public Object[] toArray() {
Object[] element=new Object[size];
int i=0;
for(Node node =head; node!=null; node= node.next){
element[i++]=node.e;
}
return element;
}
}