第2章 从C过渡到Java

第2章 从C过渡到Java

2.0 本章方法学导引

2.1 快速入门

2.1.1 Java类型概述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6SqhAZWZ-1632155034179)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20210905152225954.png)]

引用型只能按名引用(类似更换"值日生"袖标,贴在张三、李四上),不能偏移(C指针可偏移,即指针值++、–)。

另外,引用型必须要关联一个==被引用的对象,==引用才有意义。

2.1.2 输出英文希腊字母、九九乘法表

class W2{//功能:打印英文字母、希腊字母、九九乘法表
    //类W2只有两个成员(即两个函数/方法)
    int x=5;
    void prnEnChar(){//字面量
        for(char i='a';i<='z';i++)
            //System.out.print(i+'');//打印出一组数字,是因为:x+""==>产生字符串的连接,如'a'+" "==>"a" 'a'+' '==>Unicode字符'a'(无符号整数)+''(无符号整数)==>新的无符号整数
            System.out.print(i+" ");//"123"+"abc"结果为123abc
        x=x+5; System.out.print("\n x="+x+"\n ");//测试属性是所有方法的全局变量
        
    }
    void prnjj(){
        for(i=1;i<=9;i++){
            for(int j=1;j<=i;j++)
                System.out.printf("%d*%d=%2d ",i,j,i*j);
            System.out.printf("\n");//System.out.println();//ln表示line
        }
    }
}
class App{
    public static void main(String[] args){
        W2 w=new W2();//调用函数,必须先造对象
        w.prnEnChar()
    }
}
//1.通过上述编程,发现C的语法几乎都能直接使用,例外:打印System.out、main、所有东西都必须包在class里面;【【【重要:必须先造对象,再调用其方法

2.2.2 入门示例l:累加求合

与C程序相比,Java程序有一些不同

  1. ***类是Java程序的基本结构。***类的基本框架为:class 类名{类体},类体由一组变量、函数组成,均称作类的成员,其中变量也称作属性,函数也称作方法/行为。如Ch_2_1有3个成员:成员变量maxN,成员方法sum()和main()。

    #成员变量和局部变量的作用域不同。

    ​ 成员变量定义在类中、方法外,相当于方法的外部变量,故作用域是整个类,可直接应用于该类的成员方法。注:因main前有static修饰,故不可直接使用maxN。

    #成员方法:函数的返回类型需于返回值保持一致。

  2. ***组成标识符的字母范围更广。***标识符就是程序员为变量/常量、函数、类等起的名字。Java 标识符由字母、数字、下划线、货币符等字符组成,数量不限,其中数字不可作为第一个字符。关键字是语言中有特殊意义的单词,不能用作标识符。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d7CTugH3-1632155034181)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20210905180448130.png)]

  3. 输出语句不同。

    System.out.printf(…)

  4. ***调用函数的方式不同。***必须先基于类创建对象,然后基于对象调用函数。例如:

    Ch_2_1 c=new Ch_2_1();//用new 类名()创造对象

    c.sum(10);//用 对象名.函数名(实参列表); 的方式调用函数。

  5. main() 的书写方式不同。

    main()依旧是执行程序的入口,但书写格式固定:public static void main(String[] x){…}

2.1.3 理解类和对象

2.1.4 顺序表及其应用

    1. 认识Java的数组类型

      (1)Java用方括号[]来标记数组,例如:

      int [] a,b;//a、b是int[]型变量。==注:定义时不能指定容量,==如int[3]a;会报错。

      (2)必须先创建数组对象,才能引用其元素,如:

      a=new int[10]; //创建数组a引用的对象

      a[0]=5; //给数组元素赋值

      b[0]=3; //编译错,因为b并未关联数组对象,b[0]不存在。

      (3)可以在定义时创建或初始化数组对象,如:

      int [] c=new int [20];

      int [] d={1,2,3,4,5}

      (4)每个数组对象都有一个常量属性length,用于记录数组的容量。如:a.length、d.length的值分别是10、5.

    2. 理解输入类Scanner

      (1)使用前必须导入Scanner类,即在文件头部增加语句:import java.until.Scanner;

      (2) 创建Scanner对象方式为: Scanner sc=new Scanner(System.in);

      System.in代表标准输入设备,即键盘。这样通过键盘的所有输入都可从读取。数据间默认用空格分隔。

      (3)读取int型数据的方式为 : int x=sc.nextInt();

      说明:类似地,nextDouble()、nextBoolean()可以读取double、boolean型数据。

    3. 构造和使用顺序表

      从构造角度看,顺序表=数组+表长+操作集,其中数组提供顺序存储空间,表长框定数组存储数据的范围,至于操作集,可根据需要灵活定义。

    2.1.4.1 顺序表示例

    【例2.3】设计存储int型元素的顺序表类Seqlist。要求:顺序表的最大容量在创建顺序表对象时指定;包含从尾部追加、输出表中全部数据、插入元素至指定位置、排序等基本操作。

    import java.util.Scanner;//导入Scanner类,旨在告诉编译器:Scanner的位置
    //换言之,在本文件的其他地方,可以直接写Scanner,而不是写其全名:java.util.Scanner
    class Seqlist{//顺序表=数组+表长+操作集 数组有容量,相当于有容量,表长即教室的实际人数
        int [] a=new int [100];//定义数组,a的类型是int[].java中的数组对象是new出来的
       
        int len;//成员变量虽然没有赋值,但在对象构造时,均自动赋予默认值
        //数值型默认值均为0,引用型均为null,boolean默认值均为false
        //猜测所有类均有构造函数,(自己定义或编译系统自动给出。而构造函数的作用是初始化)
        //注意:局部变量没有默认值
        
         //新需求:要求在顺序表构造时之doing容量
        Seqlist(int max){a=new int[max];}//注意,用的是方括号,即未调用构造函数
        //即new int [max]造的是数组对象,该对象内有max个元素空间
       void append(int x){//向数组尾部追加元素 1 2 3 4 
           a[len]=x;len++;//修改表长   
        }
        void insert(int x,int pos){//在pos处插入x
            for(int j=len-1;j>=pos;j--)
                a[j+1]=a[j];
            a[pos]=x;
            len++;
            
        }
        void show(){//输出顺序表中的所有元素
        //void show(Seqlist *L)
            for(int i=0;i<len;i++)
                System.out.print(a[i]+" ");
        }//前万不能孤立的看一个方法,方法执行时,还要考虑其调用者,如main中的s.show、s1、show,调用者不同,调用者内部嵌入的数组也就不同。
        void sort(){
            java.util.Arrays.sort(a,0,len);
        }
    }
    class App{
        public static void main(String[] args){
            Seqlist s=new Seqlist(100);
            Seqlist s1=new Seqlist(100);
            Scanner sc=new Scanner(System.in);//其中System.in代表标准输入设备--键盘
            int x;System.out.println("请输入一组数,以0结束:");
            x=sc.nextln();//从SC中读取一个int型数据
            while(x!=0){s.append(x);x=sc.nextlnt();}
            //for(int i=0;i<10;i++)s.append(i);
            s.show();
            System.out.printIn();
            System.out.println("向s中0、2、5处插入11、22、99");
            s.insert(11,0);s.show();System.out.printIn();
            s.insert(22,2);s.show();System.out.printIn();
            s.insert(99,5);s.show();System.out.printIn();
            s.sort();
            System.out.printIn();
            s.show();        
            //System.out.printIn("S1=");s1.show();System.out.println("##");
            //System.out.printIn();
        }
    }
    

    小结:注意show()、append()无参,输入的数据直接存于数组a中(前提:a必须new出对象)。

插入三步走:第一步:先移出空位(从哪里开始,到哪里结束,如何移,移动哪些元素),第二步:实施插入a[pos]=x,第三步:修改表长:len++。

排序java.util.Arrays.sort(a,0,len);

2.1.4.2 顺序表合并

【例2.4】在例2.3的基础上,实现将两个升序表合并成新的升序表。

分析:涉及到两个对象的操作。合并:创建新表,合并到新表中,尾表的处理

  1. import java.util.Scanner;
    class Seqlist{
        int [] a=new int [100];int len;
        Seqlist(int max){a=new int[max];}
        void append(int x){a[len]=x;len++;}
        void show(){for(int i=0;i<len;i++)System.out.print(a[i]+" ");}
        void create(){
            Scanner sc=new Scanner(System.in);
            int x;System.out.println("请输入一组数,以0结束");
            x=sc.nextInt();
            while(x!=0){append(x);x=sc.nextlnt();}//注意:调用自己的方法append();
        }
        Seqlist merge(Seqlist L1,Seqlist L2){//升序表L1+升序表L2==》升序表返回
            Seqlist L=new Seqlist(100);
            int i,j,k;i=0;j=0;k=0;
            while(i<L1.len&&j<L2.len)//实施两个表的比较,小者放入新表
                if(L1.a[i]<L2.a[j]){ L.a[k]=L1.a[i];i++;k++;}
            else{L.a[k]=L2.a[j];j++;k++;}
            while(i<L1.len){L.a[k]=L1.a[i];i++;k++;}
            while(j<L2.len){L.a[k]=L1.a[j];j++;k++;}
            L.len=L1.len+L2.len;
            return L;  
        }                                                                                                   }
     class App{
         public static void main(String[] args){
             Seqlist s1=new Seqlist(100);Seqlist s2=new Seqlist(100);
             s1.create();s2.create();
             System.out.println("S1:");s1.show(); System.out.print("\n");
             System.out.println("S2:");s2.show(); System.out.print("\n");
             Seqlist s3=s1.merge(s1,s2);
             System.out.println("S3:");s3.show(); System.out.print("\n");
         }
    }                                                                                                            
    

2.1.5 单链表及其应用类

2.1.5.1

单链表=数据域+next指针+操作集。

所有引用成员都有默认值,可以省略。

头结点:指向线性表中第一个元素的第一个元素的结点;

头指针:指向线性表的第一个元素的指针。

import java.util.Scanner;
class LinkedList{
    int data;LinkedList next;
    LinkedList(int x){ data=x;}//next=null;
    //LinkedList(){;}同名不同参,即函数重载
    void create(){
        Scanner sc= new Scanner(System.in);
        int x;
        LinkedList tail,q;
        System.out.print("input: ");
        x=sc=nextInt();tail=this;//h.create()就是h,即头结点   
        while(x!=0){//造结点、把结点插入表尾、修改表尾、再读一个数据
            q=new LinkedList(x);
            tail.next=q;
            tail=q;
            x=sc.nextInt();
    }
    void show(){
        LinkedList p;
        for(p=this.next;p!=null;p=p.next)
            System.out.print(p.data+" ");
    }
    void delAll(int x){//删除链表中所有值为x元素
        //双指针移动
    }
}
class App{
    public static void main(String[] args){
        LinkedList h=new LinkedList(0);
        h.create();h.show();
    }   
}

注:没写构造函数,系统会给你补一个无参的构造函数,一旦写了,系统将不会给你补构造参数。//方法一:LinkedList(0);方法二:LinkedList(){;}同名不同参,即函数重载。

2.2 强化实践

2.2.1 二叉树及其应用

import java.util.Scanner;
//按需造类
class ReadChar{//专门用于给建树提供getchar()操作
    String data;//存储建树用的字符串
    int pos=-1;//指向当前应读的字符
    ReadChar(String x){data=x;}
    char getChar(){pos++;return data.charAt(pos);}//不能return data[pos];String的方法CharAt
    
}
class BTree{
	char data;BTree L,R;
	BTree(char x){data=x;}
	BTree(){;}
	//BTree create(ReadChar r){
    static BTree create(ReadChar r){//静态方法的特色:可不造对象,直接通过类名使用
	char x=r.getchar();
	if(x=="#")return null;
	BTree t=new BTree(x);
	t.L=create(r);t.R=create(r);
	return t;
	}
    
    void pre(){//C的方式pre(t);==>Java方式:t.pre();
        //this一定不为空,this代表对象this=t;
        System.out.print(this.data+" ");
        //this.L.pre.();this.R.pre();//注:此处可能发生空指针引用,因为this.L或this.R可能为空
        if(this.L!=null)L.pre();
        if(this.R!=null)R.pre();
    }
    class Stack{//内部类,实际上是类中作为类型的成员
        BTree[]data=new BTree[20];
        int top;
        void init(){top=0;}
        boolean isEmpty(){return top==0;}
        void push(BTree x){data[x]=x;top++}
        BTree pop(){top--return data[top--]; }
      
    }
    void preN(){
        class Stack{}//可以,类,本质上就是类型,Stack定义在preN()中,即其作用域仅限于preN()
        Stack st=new Stack();
        BTree t=this;
        while(t!=null||st.isEmpty()==false){
            if(t!=null){
                System.out.print(this.data+" ");//此句有误
                System.out.print(t.data+" ");
                st.push(t);t=t.L;}
            else{
                t=st.pop();t=t.R;
            }
        }
    }
    void inN(){
        class Stack{}//可以,类,本质上就是类型,Stack定义在preN()中,即其作用域仅限于preN()
        Stack st=new Stack();
        BTree t=this;
        while(t!=null||st.isEmpty()==false){
            if(t!=null){
                System.out.print(this.data+" ");//此句有误
                //System.out.print(t.data+" ");
                st.push(t);t=t.L;
             }
            else{
               t=st.pop(); System.out.print(t.data+" ");t=t.R;
            }
        }
    }
    
    
    void in(){
       if(this.L!=null)L.in();
       System.out.print(this.data+" ");
       if(this.R!=null)R.in();
    }    
    void post(){
       if(this.L!=null)L.post();
       if(this.R!=null)R.post();
        System.out.print(this.data+" ");  
    }
}

class App{
    public static void main(String[] args);
   // BTree t=new BTree();
    Scanner r=new Scanner(System.in)
    System.out.print("请输入建树数据,#表示null:\n")
    String x=sc.nextLine();//next读到空格时停下
    ReadChar r=new ReadChar(x);
    //t=t.create(r);//实际上,t原来的对象就被扔掉了
    BTree t=BTree.create(r);
    System.out.print("\n pre: ");t.pre();
    System.out.print("\n preN: ");t.preN();
    System.out.print("\n in: ");t.in();
    System.out.print("\n inN: ");t.inN();
    System.out.print("\n post: ");t.post();
    
}

//建树即造根,通过造一个类来输入字符。

//二叉树的前序遍历非递归算法,进入左子树前需保存当前结点供遍历右子树之用。关键:何时保存、何时用、何时删除回溯点。
/*preOrder(btree *t){
    initStack(S);
    while(t不空||栈不空)
    {
        if(t不空){
            访问t;//访问根
            保留回溯点;
             t=t->L;//访问左子树
        }
        else{
            t=回溯点;
            删除回溯点;
            t=t->R;//访问右子树
        }
    }
}*/
preOrder(btree *t){
    Stack S;
    initStack(&S);
    while(t!=NULL||栈不空)
    {
        if(t!=NULL){
            V(t);
            push(&S,t);t=t->L;
        }
        else{
            t=pop(&S);
            t=t->R;
        }
    }    
}

2.2.2 树及其应用

2.3 从内存管理视角观察程序

2.4 班级信息管理系统2.0版

2.5 一些工具类的使用

2.6 综合示例

2.7 本章小结

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值