数据结构1——线性表

线性表分为顺序表和链式表,顺序表的存储结构为数组,而链式表的存储结构为指针,那么在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&&currentNode.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)。

原文地址:https://www.cnblogs.com/xiaxj/p/6526083.html