第2章 从C过渡到Java
2.0 本章方法学导引
2.1 快速入门
2.1.1 Java类型概述
引用型只能按名引用(类似更换"值日生"袖标,贴在张三、李四上),不能偏移(C指针可偏移,即指针值++、–)。
另外,引用型必须要关联一个==被引用的对象,==引用才有意义。
2.1.2 输出英文希腊字母、九九乘法表
class W2{
int x=5;
void prnEnChar(){
for(char i='a';i<='z';i++)
System.out.print(i+" ");
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");
}
}
}
class App{
public static void main(String[] args){
W2 w=new W2();
w.prnEnChar()
}
}
2.2.2 入门示例l:累加求合
与C程序相比,Java程序有一些不同
- ***类是Java程序的基本结构。***类的基本框架为:class 类名{类体},类体由一组变量、函数组成,均称作类的成员,其中变量也称作属性,函数也称作方法/行为。如Ch_2_1有3个成员:
成员变量 maxN,成员方法 sum()和main()。
#成员变量和局部变量的作用域不同。
? 成员变量定义在类中、方法外,相当于方法的外部变量,故作用域是整个类,可直接应用于该类的成员方法。注:因main前有static修饰,故不可直接使用maxN。
#成员方法:函数的返回类型需于返回值保持一致。 2. ***组成标识符的字母范围更广。***标识符就是程序员为变量/常量、函数、类等起的名字。Java 标识符由字母、数字、下划线、货币符等字符组成,数量不限,其中数字不可作为第一个字符。关键字 是语言中有特殊意义的单词,不能用作标识符。
-
输出语句不同。 System.out.printf(…) -
***调用函数的方式不同。***必须先基于类创建对象,然后基于对象调用函数。例如: Ch_2_1 c=new Ch_2_1();//用new 类名()创造对象 c.sum(10);//用 对象名.函数名(实参列表); 的方式调用函数。 -
main() 的书写方式不同。 main()依旧是执行程序的入口,但书写格式固定:public static void main(String[] x){…}
2.1.3 理解类和对象
2.1.4 顺序表及其应用
-
认识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. -
理解输入类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型数据。 -
构造和使用顺序表 从构造角度看,顺序表=数组+表长+操作集,其中数组提供顺序存储空间,表长框定数组存储数据的范围,至于操作集,可根据需要灵活定义。
2.1.4.1 顺序表示例
【例2.3】设计存储int型元素的顺序表类Seqlist。要求:顺序表的最大容量在创建顺序表对象时指定;包含从尾部追加、输出表中全部数据、插入元素至指定位置、排序等基本操作。
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 insert(int x,int pos){
for(int j=len-1;j>=pos;j--)
a[j+1]=a[j];
a[pos]=x;
len++;
}
void show(){
for(int i=0;i<len;i++)
System.out.print(a[i]+" ");
}
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);
int x;System.out.println("请输入一组数,以0结束:");
x=sc.nextln();
while(x!=0){s.append(x);x=sc.nextlnt();}
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();
}
}
小结:注意show()、append()无参,输入的数据直接存于数组a中(前提:a必须new出对象)。
插入三步走:第一步:先移出空位(从哪里开始,到哪里结束,如何移,移动哪些元素),第二步:实施插入a[pos]=x,第三步:修改表长:len++。
排序:java.util.Arrays.sort(a,0,len);
2.1.4.2 顺序表合并
【例2.4】在例2.3的基础上,实现将两个升序表合并成新的升序表。
分析:涉及到两个对象的操作。合并:创建新表,合并到新表中,尾表的处理
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();}
}
Seqlist merge(Seqlist L1,Seqlist 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]=L2.a[j];j++;k++;}
L.len=L1.len+L2.len;
return L;
}
Seqlist merge(Seqlist L1){
Seqlist L=new Seqlist(100);
int i,j,k;i=0;j=0;k=0;
while(i<L1.len&&j<this.len)
if(L1.a[i]<a[j]){ L.a[k]=L1.a[i];i++;k++;}
else{L.a[k]=this.a[j];j++;k++;}
while(i<L1.len){L.a[k]=L1.a[i];i++;k++;}
while(j<len){L.a[k]=a[j];j++;k++;}
L.len=L1.len+len;
return L;
}
void merge1(Seqlist L1){
int [] x=new int[100];
int i,j,k;i=0;j=0;k=0;
while(i<L1.len&&j<this.len)
if(L1.a[i]<a[j]){ x[k]=L1.a[i];i++;k++;}
else{x[k]=this.a[j];j++;k++;}
while(i<L1.len){x[k]=L1.a[i];i++;k++;}
while(j<len){x[k]=a[j];j++;k++;}
len=L1.len+len;
this.a=x;
}
}
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");
s1.merge1(s2);
System.out.println("S1:");s1.show(); System.out.print("\n");
}
}
重载:可以函数同名不同参 对象的替换只要更改指针的值即可。注:this的理解要结合调用来进行:a.merge(b) 此时merge(…)中的this指代a;b.merge(a) ,此时erge(…)中的this实际上指代b。
2.1.5 单链表及其应用类
单链表=数据域+next指针+操作集。
所有引用成员都有默认值,可以省略。
头结点:指向线性表中第一个元素的第一个元素的结点;
头指针:指向线性表的第一个元素的指针。
import java.util.Scanner;
class LinkedList{
int data;LinkedList next;
LinkedList(int x){ data=x;}
void create(){
Scanner sc= new Scanner(System.in);
int x;
LinkedList tail,q;
System.out.print("input: ");
x=sc.nextInt();tail=this;
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+" ");
}
LinkedList createNoHead(){
Scanner sc= new Scanner(System.in);
int x;LinkedList h,tail,q;
System.out.print("input: ");
x=xc.nextInt();
if(x==0)return null;
h=new LinkedList(x);
x=sc=nextInt();tail=this;
while(x!=0){
q=new LinkedList(x);
tail.next=q;
tail=q;
x=sc.nextInt();
}
return h;
void showNoHead(){
LinkedList this;
for(p=this.next;p!=null;p=p.next)
System.out.print(p.data+" ");
}
void delAll(int x){
LinkedList pre,p;
pre=this;p=this.next;
while(p!=null){
if(p.data!=x){p=p.next;pre=pre.next;}
else{p=p.next;pre.next=p;}
}
}
}
class App{
public static void main(String[] args){
LinkedList h=new LinkedList(0);
h=h.createNoHead();
System.out.print("删除所有的1,结果为:\n");
h.delAll(1);
}
}
注:没写构造函数,系统会给你补一个无参的构造函数,一旦写了,系统将不会给你补构造参数。//方法一:LinkedList(0);方法二:LinkedList(){;}同名不同参,即函数重载。
2.2 强化实践
2.2.1 二叉树及其应用
import java.util.Scanner;
class ReadChar{
String data;
int pos=-1;
ReadChar(String x){data=x;}
char getChar(){pos++;return data.charAt(pos);}
}
class BTree{
char data;BTree L,R;
BTree(char x){data=x;}
BTree(){;}
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(){
System.out.print(this.data+" ");
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 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 st=new Stack();
BTree t=this;
while(t!=null||st.isEmpty()==false){
if(t!=null){
System.out.print(this.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);
Scanner r=new Scanner(System.in)
System.out.print("请输入建树数据,#表示null:\n")
String x=sc.nextLine();
ReadChar r=new ReadChar(x);
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){
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 树及其应用
【例】:设计能存储char型数据的链式K叉树结构,并实现前/后序的递归/非递归遍历。
import java.util.Scanner;
class ReadChar{
String data;
int pos=-1;
ReadChar(String x){data=x;}
char ReadChar(){pos++;return data.charAt(pos);}
}
class KTree{ final int k=3;
char data;int tag;KTree[] c=new KTree[k];
KTree(char x){data=x;}
KTree(){;}
KTree create(ReadChar r){
char x=r.Readchar();
if(x=="#")return null;
KTree t=new KTree(x);
for(int i=0;i<k;i++);t.c[i]=create(r);
return t;
}
void pre(){
System.out.print(this.data+" ");
for(int i=0;i<k;i++)if(c[i]!=null)c[i].pre();
}
void post(){
for(int i=0;i<k;i++)f(c[i]!=null)c[i].post();
System.out.print(this.data+" ");
}
class Stack{
KTree[]data=new KTree[20];
int top;
void init(){top=0;}
boolean isEmpty(){return top==0;}
void push(KTree x){data[x]=x;top++;}
KTree pop(){top--; return data[top--]; }
KTree getTop(){ return data[top-1]; }
}
void preN(){Stack st=new Stack();KTree t=this;
st.push(t);
while(st.isEmpty()==false){
t=st.getTop();
if(t==null)st.pop();
else if(t.tag==0){
System.out.print(t.data+" ");st.push(t.c[0]);t.tag++;}
else if(t.tag<k){st.push(t.c[t.tag];t.tag++;)}
else if(t.tag==k)st.pop();
}
}
}
class App{
public static void main(String[] args){
KTree t=new KTree();
Scanner r=new Scanner(System.in);
System.out.print("请输入建树数据,#表示null:\n");
String x=sc.nextLine();
ReadChar r=new ReadChar(x);
t=t.create(r);
System.out.print("\n pre: ");t.pre();
System.out.print("\n preN: ");t.preN();
System.out.print("\n post: ");t.post();
System.out.print("\n");
}
}
//28:03
==成员常量只有两处可以赋值:==1、定义时用=赋值,如k=3;2、在构造函数中赋值。
2.2.3 班级管理系统1.0
2.3 从内存管理视角观察程序
对象如何关联到方法:就数据存储而言,栈中存储函数中定义的变量,堆中存储动态创建的对象;方法区中存储运行期间动态加载的数据类型。
编译期间能确定的,统称静态…,运行期间确定的,统称动态…
基于栈、堆的内存管理:
1、栈内存管理(静态/自动内存管理):涉及函数中定义的所有变量。
2.堆内存管理(动态/手动内存管理):涉及运行期间创建的所有对象。
2.4 班级信息管理系统2.0版
2.4.1 输入输出格式化、日期、读文件
format()效果与printf()几乎相同,只不过后者是打印输出,而前者是返回格式化之后的字符串。
class Test{
public static void main(String [] x){
String s;
System.out.print("1234567890");
s=String.format("%5s","001");
System.out.print("\n"+s);
s=String.format("%-5s","001");
System.out.print("\n"+s);
s=String.format("%3.2f","12.345");
System.out.print("\n"+s);
s=String.format("%-6.2f","12.345");
System.out.print("\n"+s);
}
s=String.format("%04d",5);
System.out.print("\n"+s);
s=String.format("%7s","0中国1");
System.out.print("\n"+s);
}
import java.time.LocalDate
s=sc.next();
birthday=LocalDate.parse(s);
从文件输入
import java.io.file;
Scanner sc=new Scanner(new File("StudentInfo.txt"));
void append()throws Exception{}
public static void main(String [] x)throws Exception{}
2.4.2 学生数组的两种排序方式
2.5 一些工具类的使用
2.6 综合示例
2.7 本章小结
|