1.线性表的顺序存储结构,类似ArrayList

package collectionsFramework.linearlist;

import java.util.Arrays;

/**
* @Package collectionsFramework.linearlist * @ClassName: Singlylinkedlist * @Description: TODO(arrayList的增删改查) * @author andy * @date 2013-11-21 下午05:39:53 */
public class SinglyLinkedList<T>{
private Object[] elementData;
private int size;
private int capacity;
private int defaultCapacity = 10;
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; public SinglyLinkedList(){
capacity = defaultCapacity;
elementData = new Object[capacity];
} public int getSize() {
return size;
} public boolean isEmpty(){
return size == 0;
} //在线性顺序表的开始处添加一个元素。
public void add(T element){
insert(element , size);
}
//在指定位置处添加一个元素
private void insert(T element, int index) {
if(index < 0 || index > size){
throw new IndexOutOfBoundsException("数组下标越界!");
}
ensureCapacity(index+1);
System.arraycopy(elementData, index, elementData, index+1, size-index);
elementData[index] = element;
size++;
} private void ensureCapacity(int size) {
if(size > capacity){
//容量增大两倍,即为原来的3倍
capacity = capacity + capacity<<1;
//如果其值比最大值还大
capacity = capacity >Integer.MAX_VALUE ? hugeCapacity(size):capacity; elementData = Arrays.copyOf(elementData, capacity);
}
} //如果值比MAX_ARRAY_SIZE还大,那么其返回值就是Integer.MAX_VALUE,否则就是MAX_ARRAY_SIZE
private static int hugeCapacity(int minCapacity) {
return minCapacity > MAX_ARRAY_SIZE ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
} //删除顺序线性表中指定索引处的元素
public T remove(int index){
if(index < 0 || index > size-1){
throw new IndexOutOfBoundsException("所要删除元素的索引越界");
}
T oldData = (T)elementData[index];
System.arraycopy(elementData, index+1, elementData, index, size-(index+1));
elementData[size-1] = null;
size--;
return oldData;
} //获取顺序线性表中索引为i处的元素
public T get(int i) {
if (i < 0 || i > size - 1){
throw new IndexOutOfBoundsException("数组下标越界!");
}
return (T)elementData[i];
} public String toString()
{
if (size == 0)
{
return "[]";
}
else
{
StringBuilder sb = new StringBuilder("[");
for (int i = 0 ; i < size ; i++ )
{
sb.append(elementData[i].toString() + ", ");
}
int len = sb.length();
return sb.delete(len - 2 , len).append("]").toString();
}
} public static void main(String[] args) {
SinglyLinkedList<String> list = new SinglyLinkedList<String>();
System.out.println(list);
list.add("a");
System.out.println(list);
list.add("b");
System.out.println(list);
list.add("c");
System.out.println(list);
list.add("d");
System.out.println(list);
list.add("e");
System.out.println(list);
list.remove(2);
System.out.println("remove之后:" + list);
System.out.println(list.get(2));
}
}

2.线性表的链式实现,是一个双向链表,类似LinkedList

package collectionsFramework.linearlist;

/**
* @Package collectionsFramework.linkedlist
*
* @ClassName: DoublyLinkedList
*
* @Description: TODO(LinkedList的增删改查)
*
* @author andy
*
* @date 2013-11-21 下午05:40:31
*/
public class DoublyLinkedList<T> {
private class Node<T> {
private T data;
private Node<T> prev;
private Node<T> next; public Node() { } public Node(T data, Node<T> prev, Node<T> next) {
this.data = data;
this.prev = prev;
this.next = next;
}
} private Node<T> header;
private Node<T> tail;
private int size; public DoublyLinkedList() {
header = null;
tail = null;
} // 返回链表的长度
public int length() {
return size;
} public boolean empty() {
return size == 0;
} //在链表尾部添加新节点
public T add(T element) {
if (empty()) {
header = new Node<T>(element, null, null);
tail = header;
} else{
Node<T> newNode = new Node<T>(element , tail, null);
tail.next = newNode;
tail = newNode;
}
size++;
return element;
} //在链表头部添加新节点
public T addFirst(T element) {
header = new Node<T>(element, null, header);
if(empty()){
tail = header;
}
size++;
return element;
} public T addLast(T element) {
return add(element);
} //指定位置出插入元素
public T add(int index, T element) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("线性表索引越界");
}
// 如果还是空链表
if (empty()) {
add(element);
} else {
if(index == 0){
addFirst(element);
}else{
//插入点的前一个结点
Node<T> prev = getNudeByIndex(index-1);
//a、b、c、d
//在c这是插入一个e结点,并且它的prev指向上面的b,它的next指向d,但是b的next引用和d的prev引用还是没有变
Node<T> newNode = new Node<T>(element, prev, prev.next);
//b的next引用指向e
prev.next = newNode;
//d的prev引用指向e
prev.next.prev = newNode;
size++;
}
} return element;
} //根据索引index获取指定位置的节点,二分法查找元素
public Node<T> getNudeByIndex(int index){
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("线性表索引越界");
} if(empty()){
return null;
} if(index <= size/2){
int i=0;
for(Node<T> currentNode = header; i <= size/2 && currentNode!=null; i++,currentNode=currentNode.next){
if(i == index){
return currentNode;
}
}
}else{
int i=size-1;
for(Node<T> currentNode = tail; i > size/2 && currentNode!=null; i--,currentNode=currentNode.prev){
if(i == index){
return currentNode;
}
}
}
return null;
} //获取但不移除此列表的头(第一个元素)。
public T element() {
return getFirst();
} //获得指定索引出的数据
public T get(int index) {
if (index < 0 || index > size - 1) {
throw new IndexOutOfBoundsException("线性表索引越界");
} return getNudeByIndex(index).data;
} public T getFirst() {
return header == null? null:header.data;
} public T getLast() {
return tail == null? null:tail.data;
} public T offer(T element) {
return add(element);
} public T offerFirst(T element) {
return addFirst(element);
} public T offerLast(T element) {
return addLast(element);
} public T peek() {
return getFirst();
} public T peekFirst() {
return getFirst();
} public T peekLast() {
return getLast();
} public T poll() {
return removeFirst();
} public T pollFirst() {
return removeFirst();
} public T pollLast() {
return removeLast();
} public T pop() {
return removeFirst();
} public T push(T element) {
return addFirst(element);
} public T remove() {
return remove(0);
} public T remove(int index) {
if(index < 0 || index > size -1){
throw new IndexOutOfBoundsException("线性表索引越界");
} if(empty()){
return null;
}
Node<T> delNode;
if(index == 0){
//a、b、c、d、e 移除a结点,下面得到a结点
delNode = header;
//将b结点设置为头结点
header = delNode.next;
//并将b结点对上一个a节点的引用设置为空
delNode.next.prev = null;
//并将a结点对下一个b结点的引用设置为空
delNode.next = null;
//将删除结点设置为空
//delNode.data = null;
//delNode = null;
size--;
return delNode.data;
}else if(index == (size-1)){
//a、b、c、d、e 移除e结点,下面得到e结点
delNode = tail;
//得到d结点,并将d结点的下一点指向null
delNode.prev.next = null;
//并将e结点对上一个节点的引用设置为null
delNode.prev = null;
//将删除结点设置为空
//delNode.data = null;
//delNode = null;
size--;
return delNode.data; }else{
//a、b、c、d、e 移除c结点,下面得到c结点
delNode = getNudeByIndex(index);
//得到b结点,并将b结点的下一点指向d结点
delNode.prev.next = delNode.next;
//并将d结点对上一个节点的引用设置为b
delNode.next.prev = delNode.prev;
//并将c结点对b、d的引用设置为空
delNode.next = null;
delNode.prev = null;
size--;
return delNode.data;
}
} public T removeFirst() {
return remove(0);
} public T removeLast() {
return remove(size-1);
} public void clear() {
if(empty()){
return;
}
for (Node<T> node = header; node != null; node = node.next) {
node.data = null;
node.prev = null;
node.next = null;
}
header = null;
tail = null;
size = 0;
} public String toString()
{
//链表为空链表时
if (empty())
{
return "[]";
}
else
{
StringBuilder sb = new StringBuilder("[");
for (Node<T> current = header ; current != null
; current = current.next )
{
sb.append(current.data.toString() + ", ");
}
int len = sb.length();
return sb.delete(len - 2 , len).append("]").toString();
}
} public static void main(String[] args) {
DoublyLinkedList<String> linkedList = new DoublyLinkedList<String>();
System.out.println(linkedList);
linkedList.add("a");
linkedList.add("b");
linkedList.add("c");
linkedList.add("d");
System.out.println(linkedList);
System.out.println("移除对象:" + linkedList.removeFirst());
System.out.println(linkedList);
System.out.println("移除对象:" + linkedList.remove(2));
System.out.println(linkedList);
}
}

java_linear list的更多相关文章

随机推荐

  1. poj1080 dp

    //Accepted 200 KB 0 ms //dp //dp[i][j]表示s1用前i个,s2用前j个字符能得到的最大分数 //dp[i][j]=max(dp[i-1][j]+score[s1[i ...

  2. Linksys WRT120N路由器备份文件解析

    Perusing the release notes for the latest Linksys WRT120N firmware, one of the more interesting comm ...

  3. 使用开源工具MonoDevelop开发GTK#图形界面

    转自:http://developer.51cto.com/art/201011/235040.htm Mono一直到现在的2.8已经完全可以胜任一些比较小的项目了,但相关的开发文档与教程一直比较匮乏 ...

  4. BZOJ 3439 Kpm的MC密码

    倒着建trie,然后主席树来求子树第k大. #include<iostream> #include<cstdio> #include<cstring> #inclu ...

  5. vim的Tab设置为4个空格

    vim /etc/vimrc 1    set ts=42    set expandtab3    set autoindent 按tab键时产生的是4个空格,这种方式具有最好的兼容性.

  6. Team Foundation API - 编程控制文件版本

    Team Foundation Server (TFS)工具的亮点之一是文件的版本控制.在TFS中实现文件版本控制的类型: Microsoft.TeamFoundation.Client.TfsTea ...

  7. matlab自带princomp(PCA降维方式)

    matlab 中自带的函数就不必怀疑. princomp:principal componet analysis (PCA). [COEFF,SCORE,latent,tsquare]=princom ...

  8. php-多态

    <?php //面对对象三大特性//封装//目的:让类更安全//做法:成员变量变为私有的,通过方法来间接操作成员变量,在方法里面加限制条件 //继承//概念:子类可以继承父类的一切//方法重写: ...

  9. javascript(脚本语言)

    javascript(脚本语言)一.注释语法:1.单行注释 //注释内容2.多行注释 /*注释内容*/二.输出语法js语言格式,尽量靠下写,属双标签<script type=”text/java ...

  10. Oracle SQL语句追踪

    Oracle SQL语句追踪 1   SQL语句追踪 追踪SQL语句的执行过程需要在Oracle服务器端进行,Oracle服务器端会检测并记录访问进程所执行的所有SQL语句.下面使用的命令都是在命令行 ...