线性表分为顺序表和链式表,顺序表的存储结构为数组,而链式表的存储结构为指针,那么在java中淡化指针这个概念主要是通过对象引用的方式来表现指针。
1:顺序表
一般从两个方面来讲抽象数据类型:数据集合+操作集合
操作集合:可以将需要的操作定义为一个接口:
1 public interface List { 2 public void insert(int i, Object object)throws Exception; 3 public Object delete(int i) throws Exception; 4 public Object getDate(int i)throws Exception; 5 public int size(); 6 public boolean isEmpty(); 7 public int find(Object o); 8 }
1.1:顺序表在里面的具体实现
1 public class SeqList implements List{ 2 3 final int defaultSize=10; //设置数组的默认大小 4 5 int maxSize; //设置数组最大容量 6 int size; //设置数组的当前的容量 7 Object[] listArray; 8 9 //定义一个构造方法用于初始化数组的大小 10 public SeqList() { 11 initiate(defaultSize); 12 } 13 //该构造方法用于自己定义数组的大小 14 public SeqList(int size) { 15 initiate(size); 16 } 17 18 //定义一个构造方法用于给maxSize赋值 19 private void initiate(int sz) { 20 maxSize=sz; 21 size=0; 22 listArray=new Object[sz]; 23 } 24 /* 25 * 在数组的第i个元素(在数组的i-1的位置)上面插入一个object值,并且插入后数组的数组不变, 26 */ 27 @Override 28 public void insert(int i, Object object) throws Exception { 29 if (size==maxSize) { 30 throw new Exception("顺序表格已经插满无法插入"); 31 } 32 if (i<0||size<i) { 33 throw new Exception("请输入合适的 参数"); 34 } 35 //先移动再插入,从后面开始挪动 一定要先移动???thinking 36 for(int j=size ;i< j ; j--){ 37 listArray[j]=listArray[j-1]; 38 } 39 listArray[i]=object; 40 size++; 41 } 42 43 /* 44 * 用于删除下标为i的数,同时不破坏数组的顺序 45 */ 46 @Override 47 public Object delete(int i) throws Exception { 48 if (size==0) { 49 throw new Exception("顺序表为空无法删除"); 50 } 51 if (i<0||i>size-1) { 52 throw new Exception("参数错误"); 53 } 54 Object insert=listArray[i]; 55 //从下标为i+1的数开始挪动 56 for (int j = i; j < size-1; j++) { 57 listArray[j]=listArray[j+1]; 58 } 59 size--; 60 return insert; 61 } 62 /* 63 * 获取数组中各个元素 64 */ 65 @Override 66 public Object getDate(int i) throws Exception { 67 if (i<0||i>=size) { 68 throw new Exception("参数错误"); 69 } 70 return listArray[i]; 71 } 72 73 @Override 74 public int size() { 75 return size; 76 } 77 78 @Override 79 public boolean isEmpty() { 80 return size==0; 81 } 82 83 /* 84 * 来定义一个方法用于一次性删除多个元素,并且不破坏数组的有序性,用tag来表记是否是第一次删除元素 85 */ 86 public int MoreDataDelete(SeqList L,Object o) throws Exception{ 87 int j , i; 88 int tag=0; 89 for (i = 0; i < L.size; i++) { 90 if (o.equals(L.getDate(i))) { 91 L.delete(i); 92 i--; 93 tag=1; 94 } 95 } 96 return tag; 97 } //根据元素o查找o所在的位置 98 @Override 99 public int find(Object o) { 100 int ob=0; 101 int i=0; 102 while (i<=size&&o!=listArray[i]) 103 i++; 104 if (i>size) { 105 System.out.println("没找到"); 106 } 107 return i; 108 } 109 }
1.2:测试类
1 public class Test1 { 2 3 /* 4 * 前面insert()定义方法的时候参数一个为int类型,一个为object类型 5 * 那么传入的I,必须转化为object类型 6 */ 7 public static void main(String[] args) { 8 9 SeqList sl=new SeqList(100); 10 int n=10; 11 try { 12 for (int i = 0; i < n; i++) { 13 sl.insert(i, new Integer(i+1)); 14 } 15 sl.delete(4); 16 for (int i = 0; i < sl.size; i++) { 17 System.out.print(sl.getDate(i)+" "); 18 } 19 } catch (Exception e) { 20 e.printStackTrace(); 21 } 22 } 23 }
2:链式表
单链式表包含两个元素,数据元素+指向下一个元素的指针
同时链表又分为单链表+双向链表
双向链表包含:前指针+元素+后指针
每一个新进来的元素都是插入到head结点中去
因此首先必须有一个表示该结点的类
1 /* 2 * 整个类使用于封装节点的类 必须包含element的元素,next的节点 3 */ 4 public class Node { 5 Object element; 6 public Node next; 7 8 // 定义一个构造函数用于初始化头结点 9 public Node(Node nextval) { 10 next = nextval; 11 } 12 13 // 定义一个构造函数用于初始化除了头结点以外的节点 14 public Node(Object o, Node nextval) { 15 element = o; 16 next = nextval; 17 } 18 19 public Object getElement() { 20 return element; 21 } 22 23 public void setElement(Object element) { 24 this.element = element; 25 } 26 27 public Node getNext() { 28 return next; 29 } 30 31 public void setNext(Node next) { 32 this.next = next; 33 } 34 35 //将获得的元素转化为String类型 36 public String toString(){ 37 return element.toString(); 38 } 39 }
2.1:链式表的操作集合
1 public interface List { 2 public Object findx(Object x); 3 public void insert(int i, Object object)throws Exception; 4 public Object delete(int i) throws Exception; 5 public Object getDate(int i)throws Exception; 6 public int size(); 7 public boolean isEmpty(); 8 }
2.2:单链式表的具体实现方法
1 package com.hone.SingleLinkedList; 2 3 import com.hone.SingleLinkedList.order.Node; 4 5 public class LinList implements List{ 6 7 public Node head; //head表示头指针 8 Node currentNode; //currentNode表示当前指针 9 public int size; //表示元素的多少 10 11 //构造一个构造函数用于初始化head,currentnode节点,以及初始化size的大小 12 public LinList(){ 13 head=currentNode=new Node(null); 14 size=0; 15 } 16 17 // 定义一个方法用于确定参数i节点所在的位置,并且用当前位置的currentnode来表示i节点 18 public void index(int i) throws Exception{ 19 if(i<-1||i>size-1){ 20 throw new Exception("参数输入有误"); 21 } 22 if(i==-1) return; 23 currentNode=head.next; 24 int j=0; 25 while(currentNode!=null&&j<i){ 26 currentNode=currentNode.next; 27 j++; 28 } 29 } 30 31 // 在数组的第i个元素(i-1个结点)上面插入一个object值,并且插入后数组的数组不变 32 @Override 33 public void insert(int i, Object object) throws Exception { 34 if (i<0||i<size) { 35 throw new Exception("请输入合适的 参数"); 36 } 37 index(i-1); //找出I-1指针的位置 38 currentNode.setNext(new Node(object, currentNode.next)); 39 size++; 40 } 41 42 // 用于删除下标为i的数,同时不破坏数组的顺序 43 @Override 44 public Object delete(int i) throws Exception { 45 if (size==0) { 46 throw new Exception("顺序表为空无法删除"); 47 } 48 if (i<0||i>size-1) { 49 throw new Exception("参数错误,请输入正确的参数"); 50 } 51 52 index(i-1); //找到第i-1个结点 53 Object object=currentNode.next.getElement();//获得删除的那个元素 54 currentNode.setNext(currentNode.next.next); 55 size--; 56 return object; 57 } 58 59 // 获取数组中各个元素 60 @Override 61 public Object getDate(int i) throws Exception { 62 if (i<0||i>=size) { 63 throw new Exception("参数错误"); 64 } 65 index(i); 66 return currentNode.getElement(); 67 } 68 69 //获得单链表的大小 70 @Override 71 public int size() { 72 return size; 73 } 74 75 //判断单链表是否为空值 76 @Override 77 public boolean isEmpty() { 78 return size==0; 79 } 80 81 //根据未知数x来查找它所在的位置 82 @Override 83 public Object findx(Object x) { 84 while(currentNode!=null&¤tNode.getElement()!=x) 85 currentNode=currentNode.next; 86 return currentNode; 87 } 88 }
1 public class LinTest { 2 /* 3 * 前面insert()定义方法的时候参数一个为int类型,一个为object类型 4 * 那么传入的I,必须转化为object类型 5 */ 6 public static void main(String[] args) { 7 8 LinList ll=new LinList(); 9 int n=10; 10 11 try { 12 for (int i = 0; i < n; i++) { 13 ll.insert(i, new Integer(i+1)); 14 } 15 16 ll.delete(4); 17 for (int i = 0; i <ll.size; i++) { 18 System.out.print(ll.getDate(i)+" "); 19 } 20 } catch (Exception e) { 21 e.printStackTrace(); 22 } 23 } 24 }
2.3:双向链表的具体实现
利用链表将数组排序
1 import java.util.Comparator; 2 import com.hone.SingleLinkedList.LinList; 3 4 public class OrderList { 5 6 //为链表排序 7 public static void orderInsert(LinList mylist,Object x, Comparator mc){ 8 Node cur; 9 Node pre; 10 //每一个新进来的节点都是头结点 11 cur=mylist.head.next; 12 pre=mylist.head; 13 while (cur!=null&&(mc.compare(cur.element, x )==1)) { 14 pre=cur; 15 cur=cur.next; 16 } 17 Node temp=new Node((Integer)x, pre.next); 18 pre.next=temp; 19 mylist.size++; 20 } 21 22 public static void main(String[] args) throws Exception { 23 MyConparator mc= new MyConparator(); 24 LinList myList=new LinList(); 25 int s[] ={1,2,4,7,33,67,10,56,89,45,7,4,3}; 26 for (int i = 0; i < s.length; i++) { 27 orderInsert(myList, new Integer(s[i]), mc); 28 } 29 for (int i = 0; i <myList.size; i++) { 30 System.out.print(myList.getDate(i)+" "); 31 } 32 } 33 }
总的来说:顺序表和链式表格都有自己的优势
顺序表:因为本身数组表在逻辑+物理内存上面都是相连的,因为顺序表在随机读取,内存空间利用效率上面具有较大的优势。
但是由于顺序表,必须在事先知道数组的大小,因为可扩展性没有链式表大,其次每次插入(前面说过是从最后一项开始移动),删除都得移动较多的元素。
链式表:优点自然是不需要提前知道元素的个数。
java中已经给我们封装好了顺序表和链式表。(ArrayList/LinkedList)。
时间: 2024-10-10 20:56:03