自己实现顺序表和单链表以及他们的对比
来源:互联网 发布:mac照片和文稿里的图片 编辑:程序博客网 时间:2024/05/22 12:53
线性表包括:顺序表和单链表;顺序表是一串连着的内存空间,因此用数组来实现;单链表是分散的内存空间块,用对象来实现,一个结点是一个对象,对象里面有两个域,一个是data域,一个是nextNode域。
由于顺序表和单链表都涉及到迭代器模式,自己实现迭代器去迭代里面的数据,这里提供一个接口。
迭代器:
MyIterator类:
package cn.test.ArrayList;public interface MyIterator<T> { //是否有下一个 public boolean hasNext(); public T next(); public T remove();}
顺序表:
MyArray类:
package cn.test.ArrayList;public class MyArray<T> { private T[] elementDatas; private int length = 0; public int getLength() { return length; } //注意length和size是不同的 public int size(){ return elementDatas.length; } public MyArray() { elementDatas = (T[]) new Object[16]; } public MyArray(int initSize){ elementDatas = (T[]) new Object[initSize]; } //插入数据 public boolean insert(T data){ //判断elementDatas的长度 if(length >= size()){ //拓展长度 T[] elementDatas_temp = (T[])new Object[size() * 2 + 1]; migrate(elementDatas, elementDatas_temp); elementDatas = elementDatas_temp; } elementDatas[length++] = data; return true; } //指定位置插入数据 public boolean insert(int index, T data){ //判断插入位置的合法性 if(index < 0 || index > length){ return false; } if(length >= size()){ //拓展长度 T[] elementDatas_temp = (T[])new Object[size() * 2 + 1]; migrate(elementDatas, elementDatas_temp); elementDatas = elementDatas_temp; } if(index == length){ return insert(data); }else{ for(int i = length-1; i >= index; i--){ elementDatas[i+1] = elementDatas[i]; } elementDatas[index] = data; length++; return true; } } //在第一个位置插入数据 public boolean insertFirst(T data){ return insert(0, data); } //删除指定下标数据 public T delete(int index){ T data = null; //判断位置合法性 if(index < 0 || index >= length){ return null; } data = elementDatas[index]; //删除 for(int i = index; i <= length-1; i++){ elementDatas[i] = elementDatas[i+1]; } length --; return data; } //删除第一个数据 public T deleteFirst(){ return delete(0); } //删除最后一个数据 public T deleteLast(){ return delete(length-1); } //删除指定数据 public T delete(T data){ for(int i = 0; i < elementDatas.length; i++){ if(data.equals(elementDatas[i])){ return delete(i); } } return null; } //得到指定下面的值 public T get(int index){ return elementDatas[index]; } //得到第一个值 public T getFirst(){ return get(0); } //得到最后一个值 public T getLast(){ return get(length-1); } public MyIterator<T> iterator(){ return new MyArrayIterator(); } private void migrate(T[] from, T[] to){ for(int i = 0; i < from.length; i++){ to[i] = from[i]; } } private class MyArrayIterator implements MyIterator<T>{ private int index = 0; //未来的下标 @Override public boolean hasNext() { if(index <= length-1){ return true; } return false; } @Override public T next() { return get(index++); } @Override public T remove() { return delete(index); } } }
以上代码需要注意private class MyArrayIterator这个内部类,为什么设置为private,目的是不让外部访问。内部类可以访问外部类的方法,但外部类不可以直接访问内部类的方法,需要通过创建内部对象去访问。引申:(参考Thinking in java的内部类部分)
另外,如何创建泛型数组呢?我们知道private T[] ddTs = new T[12];
是不行的;有一个办法就是先创建Object数组,然后强制转换为T,如:private T[] elementDatas = (T[]) new Object[12];
测试方法如下:
TestMyArray类:
package cn.test.ArrayList;import org.junit.Test;public class TestMyArray { /** * 测试size、length */ @Test public void test01(){ MyArray<Integer> myArray = new MyArray<Integer>(); myArray.insert(2); myArray.insert(3); System.out.println("size:" + myArray.size() + ", length" + myArray.getLength()); MyArray<Integer> myArray2 = new MyArray<Integer>(12); System.out.println("size:" + myArray2.size()); } /** * 测试insert、delete、get */ @Test public void test02(){ MyArray<Integer> myArray = new MyArray<Integer>(2); System.out.println("size:"+myArray.size()); myArray.insert(1); myArray.insert(2); myArray.insert(3); myArray.insert(4); myArray.insert(2, 100); myArray.insertFirst(200); System.out.println("size:"+myArray.size()+" length:"+myArray.getLength()); myArray.delete((Integer)100); System.out.println(myArray.getLength()); MyIterator<Integer> it = myArray.iterator(); while(it.hasNext()){ System.out.print(it.next()+" "); } }}
以上测试方法均能得到正确的输出。
单链表:
MyOneWayLinkedList类:
package cn.test.LinkedList.OneWay;import cn.test.ArrayList.MyIterator;public class MyOneWayLinkedList<T> { private Node<T> firstNode; private int length; public int getLength() { return length; } //在第一个位置插入元素 public boolean insertFirst(T data){ Node<T> tmpNode = new Node<T>(); tmpNode.setData(data); if(null == firstNode){ firstNode = tmpNode; length++; } tmpNode.setNext(firstNode); firstNode = tmpNode; length++; return true; } //在最后的位置添加元素 public boolean insertLast(T data){ //创建一个结点 Node<T> tmp = new Node<T>(); tmp.setData(data); if(null == firstNode){ firstNode = tmp; firstNode.setNext(null); }else{ Node<T> node = firstNode; for(int i = 0; i < length-1; i++){ //for循环中,要找到哪个位置 //就要小于哪个值 node = node.getNext(); } //插入 node.setNext(tmp); } length++; return true; } //根据index插入元素 public boolean insert(int index, T data){ //判断index的合法性 if(index < 0 || index > length){ return false; } //创建结点 Node<T> node = new Node<T>(); node.setData(data); if(0 == index){ node.setNext(firstNode); firstNode = node; length++; }else{ int tmp = 0; Node<T> tmpNode = firstNode; while(tmp < index - 1){ tmpNode = tmpNode.getNext(); tmp++; } node.setNext(tmpNode.getNext()); tmpNode.setNext(node); length++; } return true; } //删除指定位置的结点 public T delete(int index){ if(index < 0 || index > length){ return null; } Node<T> tmpNode = firstNode; Node<T> returnNode = null; if(0 == index){ returnNode = tmpNode; firstNode = firstNode.getNext(); }else{ int tmp = 0; while(tmp < index - 1){ //找到删除位置 tmpNode = tmpNode.getNext(); tmp++; } returnNode = tmpNode.getNext(); tmpNode.setNext(tmpNode.getNext().getNext()); } length--; return returnNode.getData(); } //删除第一个元素 public T deleteFirst(){ if(0 == length){ return null; } Node<T> retNode = firstNode; firstNode = firstNode.getNext(); length--; return retNode.getData(); } //删除最后一个元素 public T deleteLast(){ if(0 == length){ return null; } int tmp = 0; Node<T> tmpNode = firstNode; while(tmp < length - 2){ tmpNode = tmpNode.getNext(); tmp++; } Node<T> retNode = tmpNode.getNext(); tmpNode.setNext(retNode.getNext()); length--; return retNode.getData(); } //删除指定元素 public boolean delete(T data){ if(0 == length){ return false; } if(1 == length){ if(data.equals(firstNode.getData())){ firstNode = null; length--; return true; }else{ return false; } } int index = 0; Node<T> tmpNode = firstNode; while(index < length - 1){ if(data.equals(tmpNode.getNext().getData())){ tmpNode.setNext(tmpNode.getNext().getNext()); length--; return true; } } return false; } //得到指定下标的值 public T get(int index){ //判断下标合法 if(index < 0 || index > length){ return null; } int tmp = 0; Node<T> tmpNode = firstNode; while(tmp < index){ tmpNode = tmpNode.getNext(); tmp++; } return tmpNode.getData(); } //清空链表 public void clear(){ firstNode = null; length = 0; } //获取迭代器 public MyIterator<T> iterator(){ return new MyOneWayLinkedListIterator(); } private class MyOneWayLinkedListIterator implements MyIterator<T>{ int index = 0; //未来的下标 @Override public boolean hasNext() { if(index <= length - 1){ //未来的下标在合法的范围内 return true; } return false; } @Override public T next() { return get(index++); } @Override public T remove() { return delete(index); } }}
测试方法:
TestLinkedList类:
package cn.test.LinkedList.OneWay;import org.junit.Test;import cn.test.ArrayList.MyIterator;public class TestLinkedList { @Test public void test01(){ MyOneWayLinkedList<String> myList = new MyOneWayLinkedList<String>(); myList.insertLast("1212"); myList.insertFirst("11"); myList.insertFirst("00"); myList.insert(0, "66"); MyIterator<String> it = myList.iterator(); System.out.println(myList.getLength()); while(it.hasNext()){ System.out.print(it.next()+" "); } } @Test public void test02(){ MyOneWayLinkedList<String> myList = new MyOneWayLinkedList<String>(); System.out.println("---"+myList.getLength()); myList.insertLast("1"); myList.insertLast("2"); myList.insertLast("3"); myList.insertLast("4"); myList.insertLast("5"); myList.delete(4); myList.clear(); System.out.println("---"+myList.getLength()); MyIterator<String> it = myList.iterator(); while(it.hasNext()){ System.out.print(it.next()+" "); } }}
以上测试方法均能得到正确输出
============================
顺序表和单链表的对比:
存储分配方式:
(1)顺序表:采用一段连续的存储单元一次存储数据元素
(2)单链表:采用链式存储结构,用一组任意的存储单元存储数据元素,每个存储单元都存有下一个存储单元的地址
时间性能:
1、查找:
(1)顺序表:时间复杂度为O(1)
(2)单链表:时间复杂度为O(n)
2、插入和删除:
(1)顺序表:时间复杂度为O(n),并且需要移动大量的数据元素
(2)单链表:时间复杂度为O(1),但在找到位置的过程中也需要循环,时间复杂度为O(n)
3、空间性能
(1)顺序表:创建前需要分配好多大的存储空间,这就会导致分配空间少出现内存溢出,分配空间多内存浪费
(2)单链表:创建前不需要分配空间,个数不受限制,空间利用率高
总结:经常插入删除用单链表,经常查询用顺序表
- 自己实现顺序表和单链表以及他们的对比
- 算法数据结构 单链表的实现+操作 以及和顺序表的对比
- 单链表的整表创建和删除以及顺序存储结构和链式结构的对比
- PopupWindow和AlertDlog的实现,以及他们差别
- Get和Post以及他们的区别
- .map()和.filter()以及他们的区别
- 顺序表的实现以及功能;
- 实现顺序表以及顺序表的简单运算
- 单链表和顺序表的实现
- Java单链表和顺序表性能分析对比
- 数据结构存储的顺序和链式对比
- 数据结构存储的顺序和链式对比
- 数据结构存储的顺序和链式对比
- callable和runable以及线程池对他们的执行
- 模拟memcpy和memmove函数,以及他们的区别。。
- 拦截器与过滤器的区别以及他们的执行顺序
- 拦截器与过滤器的区别以及他们的执行顺序?
- 开发自己的产品,所需要创建的makefile,以及 他们的作用
- asp.net页面时间实时更新—UpdatePanel的应用
- IOS滚动控件在滚动过程中及时停止滚动
- CSS3 动画特效(20160901-0032)
- Linux rmp相关命令
- 66. Landing Page
- 自己实现顺序表和单链表以及他们的对比
- 我所遇到的activiti问题
- HHUOJ 1012 欧洲杯(水题)
- UIImagePickerController详解
- 2016广联达面试题5
- ListView 异步加载并使用LruCache进行缓存
- 【LightOJ】1064 - Throwing Dice(dp打表)
- [leetcode][SQL]ALL
- Web初识之Servlet基础上