数据结构

数据结构 大体上分为了 线性结构和非线性结构

  如果再细分,可以把非线性结构分为 树,多维数组(2维以上),再加上集合(一般不研究)

线性结构

  1.数据元素之间存在一对一的关系

  2.数据存储有两种方式,顺序存储(一维数组)链式存储(链表),

    其中顺序存储的叫做线性表,存储的元素物理上是连续的,链式存储的叫做链表,物理上不一定连续

  3.常见的线性结构

      数组,链表,栈,队列

数组

  稀疏数组:当一个数组里面大部分的值都一样的时候,可以使用稀疏数组(列永远是3)

  只记录不同值所在的行,列,以及值(存到一个更小的数组中),以及原数组的大小和不同值的个数

  比如五子棋

 

左边是正常数组 右边是稀疏数组,右边的意思是

上边的红框存储原数组的大小和有不同的值的个数,下边的红框表示第0行第2列有一个值为1的数据 同理 第0行第3列有一个值为2的数据........

这样存储的容量小于左边的

二维转稀疏

  获得当前不同值的个数(遍历)n

  创建稀疏数组 int [n+1] [3]

  保存数据,第一行一定是二维数组的行,列,n

稀疏转二维

  先读取第一行,获得n行,m列值 创建二维数组 int [n] [m]

   去读后边的数据

  1 import java.io.*;
  2 
  3 public class MainTest {
  4     public static void main(String[] args) throws IOException {
  5             //直接赋值
  6             int[][] arr1={{0,0,0,0,0},{1,0,4,0,51},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0}};
  7             //创建一个对象
  8            /* int[][] arr2=new int[5][5];
  9             arr2[1][0]=1;
 10             arr2[1][2]=4;
 11             arr2[1][4]=51;*/
 12            //打印arr1
 13         System.out.println("二维数组:");
 14             for(int[] row:arr1) {
 15                 for (int i : row) {
 16                     System.out.print(i);
 17                     System.out.print(" ");
 18                 }
 19                 System.out.println();
 20             }
 21         //遍历arr1二维数组
 22             int count=0;
 23             for(int i=0;i<arr1.length;i++){
 24                 for(int j=0;j<arr1[i].length;j++){
 25                     if(arr1[i][j]!=0)
 26                         count++;
 27                 }
 28             }
 29             //创建稀疏数组 行为个数+1
 30             int[][] arrmix=new int[count+1][3];
 31             arrmix[0][0]=5;
 32             arrmix[0][1]=5;
 33             arrmix[0][2]=count;
 34 
 35             //把二维数组的值存入
 36          //稀疏数组的行 第0行已经存过数据了,从第一行开始
 37         int n=1;
 38         for(int i=0;i<arr1.length;i++){
 39             for(int j=0;j<arr1[i].length;j++){
 40                     if(arr1[i][j]!=0) {
 41                         arrmix[n][0] = i;
 42                         arrmix[n][1] = j;
 43                         arrmix[n][2] = arr1[i][j];
 44                         n++;
 45                     }
 46                 }
 47             }
 48         //打印稀疏数组
 49         System.out.println("稀疏数组:");
 50         /*System.out.println(arrmix[0][0]);
 51         System.out.println(arrmix[0][1]);
 52         System.out.println(arrmix[0][2]);*/
 53         for(int[] row:arrmix) {
 54             for (int i : row) {
 55                 System.out.print(i);
 56                 System.out.print(" ");
 57             }
 58             System.out.println();
 59         }
 60 
 61         //恢复为二维数组
 62         int[][] arr2=new int[arrmix[0][0]][arrmix[0][1]];
 63         for(int i=1;i<count+1;i++){
 64             arr2[arrmix[i][0]][arrmix[i][1]]=arrmix[i][2];
 65         }
 66         System.out.println("打印恢复后的");
 67         for(int[] row:arr2){
 68             for(int i:row){
 69                 System.out.print(i);
 70                 System.out.print(" ");
 71             }
 72             System.out.println();
 73         }
 74 
 75         //保存稀疏数组
 76         File file =new File("E:"+File.separator+"Data.data");
 77         System.out.println("保存稀疏数组");
 78         OutputStream fos = new FileOutputStream(file);
 79         for(int i=0;i<count+1;i++){
 80             for(int j=0;j<3;j++){
 81                 fos.write(arrmix[i][j]);
 82             }
 83         }
 84         fos.close();
 85         System.out.println("保存稀疏数组完成");
 86         //读取稀疏数组
 87         System.out.println("读取稀疏数组");
 88         InputStream fis = new FileInputStream(file);
 89         int [][] arrymixnew = new int[((int)file.length())/3][3];
 90         for(int i=0;i<((int)file.length())/3;i++){
 91            for(int j=0;j<3;j++){
 92                arrymixnew[i][j]=fis.read();
 93            }
 94         }
 95         for(int[] row:arrymixnew){
 96             for(int i:row){
 97                 System.out.print(i);
 98                 System.out.print(" ");
 99             }
100             System.out.println();
101         }
102         System.out.println("读取稀疏数组完成");
103     }
104 }

打印结果

 

队列: 有序,先进先出,先进队列的则先出去,比如排队买东西,又或者营业厅的叫号

数组可以实现队列

 1 package SF;
 2 
 3 public class ArrayQueue {
 4     private int maxSize;
 5     int a[];
 6     private int front;  //指向队列头前一个位置
 7     private int rear;   //指向队列尾数据
 8 
 9     public ArrayQueue(int maxSize){
10         this.maxSize=maxSize;
11         a=new int[maxSize];
12         front=-1;
13         rear=-1;
14     }
15 
16     public boolean isFull(){
17         return rear==maxSize-1;
18     }
19 
20     public boolean isEmpty(){
21         return rear==front;
22     }
23     public void addQueue(int n){
24         if(isFull()){
25             System.out.println("队列满");
26         }
27         rear++;
28         a[rear]=n;
29     }
30     public int getQueue(){
31         if(isEmpty()){
32             throw new RuntimeException("队列为空");
33         }
34         front++;
35         return a[front];
36     }
37     public void showQueue(){
38         if(isEmpty()){
39             System.out.println("队列为空");
40         }
41         for(int i=0;i<a.length;i++){
42             System.out.println(a[i]);
43         }
44     }
45     public int peekQueue(){
46         if(isEmpty()){
47             throw new RuntimeException("队列为空");
48         }
49         return a[front+1];
50     }
51 }

循环队列:队列的重复利用(预留一个空数据位)

当然判断队列是否是满的条件也会发生变化,判断队列为空 rear==front

判断队列是否是满的 (rear+1)%maxSize==front

队列有效的数据个数 (rear+maxsize-front)%maxSize

 数组实现循环列表

package SF;

public class CircleArrayQueue {

    private int maxSize;
    int a[];
    private int front;  //指向队列头数据
    private int rear;   //指向队列尾数据的后一个位置

    public CircleArrayQueue(int maxSize) {
        this.maxSize = maxSize;
        a = new int[maxSize];
        //front和rear默认wei0
    }

    public boolean isFull() {
        return (rear+1)%maxSize==front;

    }

    public boolean isEmpty() {
        return rear == front;
    }

    public void addQueue(int n) {
        if (isFull()) {
            System.out.println("队列满");
        }
        a[rear] = n;
        rear=(rear+1)%maxSize;
    }

    public int getQueue() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空");
        }
        int i = front;
        front=(front+1)%maxSize;
        return a[i];
    }

    public void showQueue() {
        if (isEmpty()) {
            System.out.println("队列为空");
        }
        for (int i = front; i < getNum(); i++) {
            System.out.println(a[i%maxSize]);
        }
    }

    public int peekQueue() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空");
        }
        return a[front + 1];
    }

    public int getNum(){
        return (rear+maxSize-front)%maxSize;
    }
}

 

链表

链表是以节点方式存储

每个节点包含数据域和next域

next域指向下一个节点(存储下一个节点的位置)

物理上不一定连续,其中还分为带头(头结点)链表和不带头(不带头链表)

不排序的带头链表

package SF;

public class SingleLinkListDemo {
    public static void main(String[] args){
       PersonNode personNode1 = new PersonNode(1,"zhangsan",1);
       PersonNode personNode2 = new PersonNode(2,"lisi",2);
       PersonNode personNode3 = new PersonNode(3,"wangwu",3);
       SingleLinkList sll = new SingleLinkList();
       sll.addNode(personNode1);
       sll.addNode(personNode2);
       sll.addNode(personNode3);
       sll.list();
    }
}
class SingleLinkList{
    //先初始化一个头节点
    private PersonNode pn = new PersonNode(0,"",0);
    //添加节点
    public void addNode(PersonNode personNode){
       PersonNode temp = pn;
       //遍历链表寻找最后一个节点
       while(true){
           //找到了
           if(temp.nextPersonNode==null){
               break;
           }
           //没找到
           temp=temp.nextPersonNode;
       }
       //找到后推出循环,此时temp指向最后一个节点,并将传入的新节点赋给temp,此时的temp.nextPesonNode指向新节点
       temp.nextPersonNode=personNode;
    }
    //显示节点
    public void list(){
        //判断是否为空链表
        if(pn.nextPersonNode==null){
            System.out.println("链表为空");
        }
        //辅助节点
        PersonNode temp = pn.nextPersonNode;
        //遍历
        while(true){
            if(temp == null){
               break;
            }
            System.out.println(temp);
            temp=temp.nextPersonNode;
        }
    }
}
//定义节点
class PersonNode{
    private int id;
    private String name;
    private int age;
    public PersonNode nextPersonNode;
    public PersonNode(int id,String name,int age){
        this.id=id;
        this.name=name;
        this.age=age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public PersonNode getNextPersonNode() {
        return nextPersonNode;
    }

    public void setNextPersonNode(PersonNode nextPersonNode) {
        this.nextPersonNode = nextPersonNode;
    }

    //方便显示
    @Override
    public String toString() {
        return "PersonNode{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

排序的带头链表

public void addByOrder(PersonNode personNode){
        PersonNode temp = pn;
        //确保不会重复添加
        boolean flag=false;
        while(true) {
            //temp是最后一个节点
            if (temp.nextPersonNode == null) {
                break;
            }
            if(temp.nextPersonNode.getId()>personNode.getId()){//找到位置temp后插入
                break;
            }else if(temp.nextPersonNode.getId()==personNode.getId()){  //相同id已经存在
                    flag=true;
                    break;
            }else {
                temp=temp.nextPersonNode;
            }
        }
        if(flag){
            System.out.println("要插入数据已存在,不能重复插入");
        }else{
            //下边两句顺序不能搞反,不然找不到了
            personNode.nextPersonNode = temp.nextPersonNode;
            temp.nextPersonNode = personNode;
        }
    }

删除节点

public void del(PersonNode personNode){
       boolean flag=false;
       if(pn.nextPersonNode==null){
           System.out.println("链表为空,不能删除");
       }
       PersonNode temp = pn;
       while(true){
           if(temp.nextPersonNode==null){
               break;
           }
           if (temp.nextPersonNode.getId()==personNode.getId()){
               flag=true;
               break;
           }
           temp=temp.nextPersonNode;
       }
        if(!flag){
            System.out.println("没有找到要删除的节点");
        }else{
            temp.nextPersonNode=temp.nextPersonNode.nextPersonNode;

        }

    }

修改节点

public void update(PersonNode personNode){
        if(pn.nextPersonNode==null){
            System.out.println("链表为空");
        }
        PersonNode temp = pn.nextPersonNode;
        //判断是否找到的标志
        boolean flag = false;
        while(true){
            //遍历完毕没找到
            if(temp==null){
                break;
            }
            if(temp.getId()==personNode.getId()){
                flag = true;
                break;
            }
                temp=temp.nextPersonNode;
        }
        if(!flag){
            System.out.println("未找到要修改的节点");
        }else{
            temp.setName(personNode.getName());
            temp.setAge(personNode.getAge());
        }
    }

 

 ------------------------------------------未完待续,继续补充---------------------------------------------------------------

 

posted @ 2019-06-15 12:33  义乂义乂义乂  阅读(217)  评论(0编辑  收藏  举报