美文网首页
数据结构.Java.基本内容(上)

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

作者: TwistedFateJie | 来源:发表于2018-03-16 12:26 被阅读0次

    数据结构基本介绍(上)

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

    这里写图片描述

    二.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),
      <code>public void addNodeAfter(int element){
      //调用该方法后,生成一个数据域为element,link域与selection.link相同的结点
      //构造函数返回了引向新建结点的引用
      link = new IntNode(element,link);
      }</code>
      分析:selection.addNodeAfter(42),假设前一个结点的数据为20
      1.selection为数据为20的结点的引用
      2.link = new IntNode(42,link),其中,link来自所选结点,即link就是selection.link。该语句的右侧执行了构造函数,生成一个数据为42,link域与selecion.link相同的新结点。构造函数返回引向新创建结点的引用(<font color="red">理解成:修改所选结点的link域,使其引向新创建的结点</font>)。

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

    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 ArrayStack<E>clone(){
            ArrayStack<E> answer;
            try{
                answer = (ArrayStack<E>) 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<Character> q = new LinkedList<>();
            java.util.Stack<Character> 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只增不减。到达数组末端后,数组中可能还有未填充的数组单元。


      数组data

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


      这里写图片描述
    public class ArrayQueue<E> {
        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.基本内容(上)

          本文链接:https://www.haomeiwen.com/subject/ccblqftx.html