自制链表队列 同 系统库中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);
	}

我的:
在这里插入图片描述
系统:
在这里插入图片描述

  • 之前在写查询的时候就想有没有办法优化,,现在终于找到了方法。。

又捕获一种学习方法~~

发布了45 篇原创文章 · 获赞 14 · 访问量 2492

猜你喜欢

转载自blog.csdn.net/qq_44357371/article/details/102712128
今日推荐