JAVA动态数组的实现——链表

前面我们已经使用顺序表实现了一个动态数组,当然动态数组还有另一种实现形式——链表。这里就涉及到另一个问题,JAVA中有没有指针?严格来说JAVA是没有真正意义上的指针的,它只有引用。具体的分析我们这里暂不做讨论。接下来我们就利用JAVA的引用来实现一个动态数组,也就是链表。

一、链表的物理结构

链表是由一个个独立的节点组织起来的,它具有真正意义上的动态。顺序表在计算机内部是顺序储存的,它每次在创建时都要求开辟一个连续的内存空间。而链表不同,由于链表的每一个节点都可以通过引用找到它的下一个相邻节点,因此它在计算机内部是离散储存的。每一个节点都是独立的单位。因此每当你需要增加一个节点时,我们就创建一个新节点保存要增加的数据,并且通过引用,把最后一个节点的引用指向这个新节点。同样的,如果要删除一个节点,我们就把该节点删除掉,再改变其前后节点引用的指向即可。我们可以看一下下图

根据上面的分析我们可以知道链表的节点需要有两个信息,一个是数据对象——储存待保存对象,另一个是节点引用——指向该节点的下一相邻节点。

二、链表的方法实现

1.添加元素的方法——append()

基本步骤:A.新建一个节点(data储存新数据,next为空);B..找到最后一个节点;C.修改最后一个节点的next引用,使其指向新建的节点

2.获取任意位置数据的方法——get()

基本步骤:判断index是不是0,如果是0直接返回根节点的数据;否则通过循环找到相应的节点,然后返回相应节点的数据

3.返回当前链表大小的方法——size()

定义一个int型数据len,每次调用append()或者insert()等会改变当前数组数据个数的操作时都相应地增加或者减少len的大小

4.在指定位置插入数据的方法——insert()

A.新建一个保存待插入数据的新节点

B.判断要插入的位置是不是根节点的位置,如果是,则将该节点的next指向当前的根节点,再把根节点指向这个新建的节点;如果不是,就需要改变该位置的前后两个节点的指针


5.删除指定位置数据的方法——delete()

A.保存要删除的节点

B.判断是不是根节点,如果是,则将根节点的引用head指向它的下一节点(即移动根节点);如果不是,则将该节点前一个节点的next指向该节点的next

三、具体代码实现

//创建一个用链表实现的动态数组类DynamicArray
public class DynamicArray {
	Node head;//定义一个头节点,head不存数据
	Node curr;//定义一个当前节点
	int size;//定义一个储存数组长度的数据
	
	//需要一个节点类
	public class Node {
		Object data;//这个节点的数据
		Node next;//指向下一个节点
		
		public Node(Object data) {
			this.data=data;
		}
	}
	
	//需要一个添加方法
	public void append(Object o) {	
		Node newNode=new Node(o);
		if(head==null) {
			head=newNode;
			head.next=null;
			curr=head;//移动当前节点的位置
		}
		//从第一个位置开始找
		else {
			//移动当前节点的位置
			curr.next=newNode;
			curr=curr.next;
		}
		size++;//数组大小加1
	}
		
	//需要一个获取节点信息的方法
	public Object get(int index) {
		int position = 0;
		Node temp=head;
		while(position<index) {
			temp=temp.next;
			position++;
		}
		return temp.data;
	}
	
	//获取当前动态数组的长度
	public int size() {
		return size;
	}
	
	//在指定位置插入一个数据
	public void insert(Object o,int index) {
		Node newNode=new Node(o);
		if(index==0) {
			newNode.next=head;
			head=newNode;//重新设置头节点
		}
		else {
			int position = 0;
			Node temp=head;
			//获取待插入位置的前一个位置
			while(position<index-1) {
				temp=temp.next;
				position++;
			}
			newNode.next=temp.next;
			temp.next=newNode;
		}
		size++;
	}
	
	//在指定位置删除数据
	public Object delete(int index) {
		Object retuNode;
		if((size==0)||(index>size-1)) {
			System.out.println("操作有误");
		}
		//如果删除的是头结点
		if(index==0) {
			retuNode=head.data;
			head=head.next;//直接移动头节点的位置即可
		}
		else {
			int position = 0;
			Node temp=head;
			//获取待插入位置的前一个位置
			while(position<index-1) {
				temp=temp.next;
				position++;
			}
			retuNode=temp.next.data;
			temp.next=temp.next.next;
		}
		size--;
		return retuNode;
	}
}
//定义一个测试类
public class Test {
	public int number;
	public String name;
	
	public Test(int number,String name) {
		this.number=number;
		this.name=name;
	}
	
	
	public static void main(String[] args) {
		Test t1=new Test(1,"a");
		Test t2=new Test(2,"b");
		Test t3=new Test(3,"c");
		Test t4=new Test(4,"d");
		
		DynamicArray Array1=new DynamicArray();
		Array1.append(t1);
		Array1.append(t2);
		Array1.append(t3);
		int len1=Array1.size();
		System.out.println(len1);
		Test testT1=(Test)Array1.get(0);
		System.out.println(testT1.number+":"+testT1.name);
		
		Array1.insert(t4, 0);
		int len2=Array1.size();
		System.out.println(len2);
		Test testT2=(Test)Array1.get(0);
		System.out.println(testT2.number+":"+testT2.name);
		
		Array1.delete(0);
		int len3=Array1.size();
		System.out.println(len3);
		
		Test testT3=(Test)Array1.get(0);
		System.out.println(testT3.number+":"+testT3.name);
		
	}
}

四、总结——顺序表和链表

1.储存方式不同:顺序表在计算机中是连续储存的,而链表是离散储存的。

2.适用场景:顺序表适用于索引操作比较多的应用场景,而链表适用于插入删除操作比较多的适用场景。


猜你喜欢

转载自blog.csdn.net/alexwym/article/details/80959315