自制鏈表隊列 同 系統庫中LinkedList 方法性能對比

本文介紹用鏈表實現一個隊列,並同系統隊列比較在運行一千萬個數時增、刪、查功能的性能

首先,創建結點,包括next、data屬性

我的:
private node root;	//根節點
private node last;	//尾節點
public int size = 0;	//鏈表的大小

public class node {	//創建結點類
	public object data;	//結點中存放的數據值
	public node next;	//指向下一個結點

	public node(object data, node next) {	//構造
		this.data = data;
		this.next = next;
	}
}

在Java jdk中,它直接定義了前趨結點,然而我的是在後面的方法中新創建的

Java jdk:
private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {	//傳入三個參數:前趨、此元素、後繼
            this.item = element;	//結點中存放的值
            this.next = next;
            this.prev = prev;	//前趨結點
        }
    }

入隊:

我的:
// 新元素從尾部進隊列
public void In_Queue(Object obj) {
	node newNode = new node((object) obj, null);
	if (root == null) {		//當隊列爲空,把新數據放入根節點中
		root = last = newNode;
	} else {		//隊列非空,從尾部入隊
		last.next = newNode;		
		last = last.next;
	}
	size++;
}

Java jdk中

Java jdk:
void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);		//新結點的前趨是尾節點,後繼是null,即新定義尾結點
        last = newNode;
        if (l == null)
            first = newNode;	//隊空
        else
            l.next = newNode;	
        size++;
    }

入隊操作兩者比較:
通過比較添加10000000個數所需要的時間,對比兩個方法的性能

	LinkedList<Object> list = new LinkedList<>();
	long start = System.currentTimeMillis();
	for (int i = 0; i < 10000000; i++) {
		list.add(i);
	}
	long end = System.currentTimeMillis();
	System.out.println(end - start);

外套一個循環,運行10次的結果:

我的程序:
在這裏插入圖片描述
系統:
在這裏插入圖片描述

  • 首先,感覺系統的代碼更簡潔,它在創建結點的時候,直接傳入三個參數,後面用着就很方便
  • 系統程序在新建結點的時候就已經建立好last和newNode的關係了,然而我的程序,新建結點且賦值之後,還要把新結點設置爲尾結點。

出隊

我的:
// 從隊首刪除元素
	public void Out_Queue() {
		node preNode = new node(null, null);	//新建前趨結點
		preNode = root;		//指向根節點
		if (size == 0) {
			System.out.println("隊空");
		} else {
			root.data = null;	//把根節點的內容幹掉
			root = root.next;	//根節點的後結點變成根節點(假溢出的根源)
			size--;
		}
	}
Java jdk:
private E unlinkFirst(Node<E> f) {
        // assert f == first && f != null;
        final E element = f.item;
        final Node<E> next = f.next;	//和我的preNode一個效果
        f.item = null;
        f.next = null; // help GC
        first = next;		//把f.next指向first
        if (next == null)	//用f.next判斷隊空(我用的是最初創建好的計數器size)
            last = null;
        else
            next.prev = null;	//頭節點的下一個結點的前趨結點(頭節點)變成null
        size--;
        return element;
    }

下面進行測試
先進隊10000000個數,然後幾下這些數出隊的時間

public static void main(String[] args) {
		long S = 0;
		for (int m = 0; m < 10; m++) {
			Queue queue = (Queue) Init_Queue();
			for (int i = 0; i < 10000000; i++) {
				queue.In_Queue(i);
			}
			long start = System.currentTimeMillis();
			for (int i = 0; i < 10000000; i++) {
				queue.Out_Queue();
			}
			long end = System.currentTimeMillis();
			long S1 = end - start;
			System.out.println(end - start);
			S = S + S1;
		}![](https://img-blog.csdnimg.cn/20191024004340605.png)
		System.out.println("平均時間" + S / 10);
	}

我的程序:
在這裏插入圖片描述
系統:
在這裏插入圖片描述

  • 我的時間竟然比它的短!!!我驚呆了
  • 個人認爲是因爲它用的那個 prev ,我在把根節點變成null後,直接把根節點的後結點變成根節點;而系統程序是根節點的下一個結點的前趨結點變成null。
  • 刪除一個結點,比增加一個結點快了n倍。

查找

我的:
// 查找元素
	public void Find(int index) {
		node goalNode = new node(null, null);
		goalNode = root;
		if (index < 0 || index >= size) {
			System.out.println("超出範圍!!!");
		} else if (index == 0) {
			// System.out.println(goalNode.data);
		} else {
			for (int i = 0; i < index; i++) {	//通過頭結點遍歷(感覺很不妥)
				goalNode = goalNode.next;
			}
			// System.out.println(goalNode.data);
		}
	}
Java jdk:
//判斷插入的位置和總長度的關係,優化
	public E get(int index) {
        checkElementIndex(index);	//判斷是否超出存儲的長度
        return node(index).item;
    }
    
    Node<E> node(int index) {
        // assert isElementIndex(index);
        if (index < (size >> 1)) {		//如果插入的位置小於鏈表總長度一半
            Node<E> x = first;			//從頭節點開始往後
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;		//如果大於一半
            for (int i = size - 1; i > index; i--)		//從尾節點往前
                x = x.prev;
            return x;
        }
    }

不用看運行結果就知道,肯定是系統的快,機智!!

但是呢,還是數字更有說服力,我通過設定500個1-10000000的隨機數讓它去查詢來比較結果:

public class Main {
	public static void main(String[] args) {
		long S = 0;
		for (int n = 0; n < 10; n++) {
			LinkedList<Object> list = new LinkedList<>();
			for (int i = 0; i < 10000000; i++) {
				list.add(i);
			}
			
			long start = System.currentTimeMillis();
			for(int i = 0;i<50;i++){
				Random random =new Random();
				int index = random.nextInt(10000000)+1;
				list.get(index);
			}
			long end = System.currentTimeMillis();
			
			long S1 = end - start;
			System.out.println(end - start);
			S = S + S1;
		}
		System.out.println("平均時間" + S / 10);
	}

我的:
在這裏插入圖片描述
系統:
在這裏插入圖片描述

  • 之前在寫查詢的時候就想有沒有辦法優化,,現在終於找到了方法。。

又捕獲一種學習方法~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章