数据结构.Java.基本内容(上)

数据结构基本介绍(上)

*本文为《数据结构(Java语言描述)》一书的线上笔记

数据结构.Java.基本内容(上)_第1张图片
这里写图片描述

二.Java类与信息隐藏

  1. 面向对象程序设计
    一种程序设计方法,将数据存储在对象中,通过方法来调用操作对象。类是创建对象和方法的机制。

三.集合类###

数组
注意:
*数组变量是引用变量,使用new操作符来创建。int[] scores = new int[4],scores将引用具有4个整型元素的数组。
*在使用数组前一定要先创建数组。要防止数组越界。
*使用赋值语句"="时,赋的是数组的引用。
*若要克隆出一个独立数组,则使用方法clone();

使用数组实现集合类


四.链表

链表需要动态地缩减和增长使用的内存。链表是一个接一个排列的元素序列,常用的程序设计方式是将每个元素与指向下一个元素的“指针”放置在一起,构成一个结点。其中,最后一个结点不再指向下一个结点。

代码示例(IntNote类):

声明:

 //存储在该结点中的元素
    private int date;
    //最后一个结点为null
    //在链表中引用下一个结点
    private IntNode link;
    public IntNode(int initalDate,IntNode initialLink){
        date = initalDate;
        link = initialLink;
    }
    //省略data,link的get,set方法。

操作链表:

  1. 在链表头添加新结点
    首先,需要一个引向链表头结点的引用head。使用head = new IntNode(5,head),该语句首先创建一个数据为5的新结点,因为head存储的是下一个结点的引用,故该结点引向下一结点的引用。

  2. 在链表头部删除结点
    首先,需要一个引向链表头结点的引用head,删除第一个结点,只需使用head = head.getLink()。使head引向下一个结点。

  3. 添加链表中非头部结点
    首先,需要一个引向新结点预期位置之前的结点的引用(所选结点引用selection),
    public void addNodeAfter(int element){
    //调用该方法后,生成一个数据域为element,link域与selection.link相同的结点
    //构造函数返回了引向新建结点的引用
    link = new IntNode(element,link);
    }

    分析:selection.addNodeAfter(42),假设前一个结点的数据为20
    1.selection为数据为20的结点的引用
    2.link = new IntNode(42,link),其中,link来自所选结点,即link就是selection.link。该语句的右侧执行了构造函数,生成一个数据为42,link域与selecion.link相同的新结点。构造函数返回引向新创建结点的引用(理解成:修改所选结点的link域,使其引向新创建的结点)。

  4. 删除链表中非头部结点
    首先,需要一个引向新结点预期位置之前的结点的引用(所选结点引用selection)。要将刚才添加的结点删除,selection则应为引向数据为20的结点,我们只需将selection的link域赋值为link.link,即引向下下个结点的引用。
    public void removeNodeAfter(){
    link = link.link;
    //潜在空指针异常
    }

  5. 操作整个链表
    使用静态(保证链表为空时依然可用)方法listLength获得链表的长度

public static int listLength(IntNode head){
        //用于遍历链表的引用变量
        IntNode cursor;
        int answer = 0;
        //当cursor引向尾结点时,cursor.link = null,条件不成立,跳出循环。
        for(cursor = head;cursor != null;cursor = cursor.link){
            answer ++ ;
        }
        return  answer;
    }

在for循环中,我们可以执行诸如查找元素这样的代码

  1. 复制一个链表
 }
    //普通方法不能复制空链表,空链表是以空引用的方式表示的
    public static IntNode listCopy(IntNode source){
        IntNode copyHead;
        IntNode copyTail;
        if(source == null){
            return  null;
        }
        //为新链表生成第一个结点
        //头、尾结点都引向该结点
        copyHead = new IntNode(source.date,null);
        copyTail = copyHead;

        //添加其余结点
        while(source.link != null){
            source = source.link;
            copyTail.addNodeAfter(source.date);
            copyTail = copyTail.link;//

        }
        return  copyHead;
    }

实际中,常常需要返回一个包含头尾结点引用的数组。此时只需新建一个数据长度为2的数组。将头尾结点的引用赋值给数组后返回数组即可。


五.通用程序设计

使用一些普遍适用于许多场合的类。

Java中的Object类型

Object的变量能保存引向任意类型的对象的引用。
*拓展转换

 String s = new String("I am a String");
 Object obj;
 //拓宽转换
 obj = s;

*削窄转换
s = (String)obj,需要强制类型转换

Object方法和通用方法####

Object方法:
*可能会出现隐式的类型错误。
通用方法(使用泛型):


六.栈

一种由有序数据项构成的数据结构,数据项的插入及删除只能在栈顶进行。是一种后进先出的数据结构(LIFO)。可以把栈类比成一个存储硬币的圆柱容器,该容器只有顶端一个开口。往其中放入硬币称为压栈(push),从最上面取出一个称为出栈(pop),只查看第一个硬币而不拿动称为peek。

一个简单的例子,实现带全括号的基本算术运算:

代码暂略

栈的数组实现:

  1. 变量声明与构造函数
     //数据总个数
    private int manyItems;
    //栈底元素为data[0],栈顶元素为data[manyItems-1]
    private E[] data;

    public ArrayStack(){
        final int INITIAL_CAPCITY = 10;
        manyItems = 0;
        data =(E[]) new Object[INITIAL_CAPCITY];
    }
    
    public ArrayStack(int initialCapcity){
        if(initialCapcity < 0){
            throw new IllegalArgumentException();
        }
        manyItems = 0;
        data =(E[]) new Object[initialCapcity];
    }
  1. 栈的基本操作
 //改变栈的当前容量
    public void ensureCapacity(int minimumCapacity){
        E biggerArray[];
        if(data.length < minimumCapacity){
            biggerArray = (E[])new Object[minimumCapacity];
            System.arraycopy(data,0,biggerArray,0,manyItems);
            data = biggerArray;
        }
    }
    //获得栈顶元素
    public E peek(){
        if(manyItems == 0){
            throw  new EmptyStackException();
        }
        return  data[manyItems - 1];
    }
    //出栈
    public E pop(){
        E answer;
        if(manyItems == 0){
            throw new EmptyStackException();
        }
        answer = data[--manyItems];
        data[manyItems] = null;
        return  answer;
    }

    //压栈
    public void push(E item){
        if(manyItems == data.length){
            ensureCapacity(manyItems*2 + 1);
        }
        data[manyItems] = item;
        manyItems ++;
    }
  1. 复制一个副本
    该类要实现Clone
public ArrayStackclone(){
        ArrayStack answer;
        try{
            answer = (ArrayStack) super.clone();
        }catch(CloneNotSupportedException e){
            throw new RuntimeException("This class does not implement Cloneable");
        }
        answer.data = data.clone();
        return  answer;
    }
  1. 4

栈的链表实现:
使用链表,不需要担心容量(链表可动态增减数据项)。
实例变量top是引向链表数据项头结点的引用。


七.队列

队列是一种先进先出(FIFO)的数据结构(类比排队)。只能在队尾插入数据,从队头取出数据。队列中的数据项和栈一样,可以是任意类型的。

与栈相结合,实现一个简单的工具:检测回文

public static boolean isPalindrome(String input){
/**
Character类是对单个字符进行操作。
*/
        java.util.Queue q = new LinkedList<>();
        java.util.Stack s = new Stack<>();
        Character letter ;
        //不匹配的点的数量
        int misMatches = 0;
        int i ;
        for( i = 0; i< input.length();i++){
            letter = input.charAt(i);
            if(Character.isLetter(letter)){
                q.add(letter);
                s.push(letter);
            }
        }
        while(! q.isEmpty()){
            if(q.remove( ) != s.pop()){
                misMatches++;
            }
        }
        return (misMatches == 0);
    }

队列的数组实现:

  1. 实现思路:
    使用部分填充的数组实现队列。队列可以在两端访问数据,同样,已填充部分数组也需要在两端访问数据。使用变量front,rear分别表示已使用数组的第一项及最后一项。添加数组项时,只要不断的将rear增加1。这样一来,rear只增不减。到达数组末端后,数组中可能还有未填充的数组单元。


    数据结构.Java.基本内容(上)_第2张图片
    数组data

    上图中,删除数据项A,B后,添加两个数据E,F到队尾的尾部。如果我们想再添加一个数据G,发现数组末端已经没有空余,我们把G添加到右图数组的data[0]。此时rear的下标为0。rear=0 < front = 2;此时,我们把数组看成环,这样的数组称为循环数组。


    数据结构.Java.基本内容(上)_第3张图片
    这里写图片描述
public class ArrayQueue {
    private E[] data ;
    private int manyItems ;//记录队列中数据项的个数
    /**
     * front data[front],连续向前,到达数组的末端,返回data[0]
     */
    private int front;
    private int rear;

    public ArrayQueue(){
        //默认数组大小
        final int INITIAL_CAPACITY = 10;
        manyItems = 0;
        data = (E[])new Object[INITIAL_CAPACITY];

    }
  1. 3
  2. 4
  3. 5

八.递归思想

递归:在方法的内部调用该方法;
递归思想:子任务与开始时要解决的问题相同,只不过是一具比较简单的版本。我们要做的,就是找出问题的简单版本。

简单的例子:
实现输入整数,输出它所有位。

public static void writerVertical(int number){
        if(number < 0){
            writerVertical(-1*number);
        }else if(number < 10 ){
            System.out.println(number);
        }else{
            writerVertical(number/10);
            System.out.println(number % 10);

        }
    }

说明

  • 1
  • 2
  • 3
  • 4
  • 5

你可能感兴趣的:(数据结构.Java.基本内容(上))