*经典数组赋值语句
int[] Arr = new int[]{1,2,3,4,5};
//从右向左执行,在堆内存中创建了长度指定,元素指定的一维int型数组,在主函数中创建了一个名为Arr的变量,将数组在堆内存中的地址赋给Arr一维数组型变量,以供Arr调用,从而实现对数组元素中的改变;
Arr[2] = 10;
//角标为2,事实上是第三个元素,将10这个整型值赋给Arr数组中的第三个元素
int[] Arr2 = arr;
//*易混淆点,此处实际并未开辟堆内存中的新空间,只不过是变量间的赋值,但是不是赋的是一个具体的数值,而是将Arr变量的地址赋给了Arr2这个变量,但是Arr的地址实际是堆内存中一维数组的地址,此时指向一维数组的变量有两个,Arr从而将地址赋给Arr2,使Arr2获得了对一维数组的调用访问修改数值的权利;
Arr2[2]= 20;
//Arr2变量通过地址寻找访问到了一维数组(仅有的一个数组)并对其中角标为2,实际为一维数组中的第三个元素进行了重新赋值为20,数组中实际第三个元素值已经变更为20
System.out.println(Arr[2]);//此时调用打印输出语句,打印的是Arr变量访问一维数组中的角标为2,实际为第三个元素,但是刚才Arr2已经通过变量地址访问到并修改其值,此时Arr变量在访问并打印,实际打印出来的为20;
Arr=null;
//将Arr中的变量地址赋值为空,此时Arr已无法通过地址查找访问一维数组。
System.out.println(Arr[2]);
//此时仍是将Arr[2]元素打印出来,但是Arr变量地址已经赋值为空,Arr变量此时将再无法访问一维数组,但是整体输出语句语法没有错误,编译不会出错,但是运行时泽会出现java.lang.NullPointerException (空指针异常)
当一个对象(数组或者后面所学知识点)再也没有被其他变量引用(此时已无变量知道对象在堆内存中的地址)时,就变成了垃圾(由垃圾回收器自动回收)
java中字符串和数组分别获得长度的方法
//字符串String的长度 length() 函数
//数组[]的长度 length 属性/变量
二分搜索
二分搜索的前提为数组是有序的,数组已经按照正序或者逆序排列,时间复杂度O(n)更低,仅为log以2为低n的对数,因为没进行一次搜索,就可以排除一半的元素,但在加快搜索的同时,空间变得更加复杂了;
二分搜索的代码实现
数组的扩容
(1)数组的长度一旦确定不可以更改(本质为为数组开辟的连续空间大小不可变)
(2)数组的扩容或者缩容的本质并不是在原数组上进行操作的,而是在堆内存中重新开辟了新的空间,创建了我们的一个新数组,长度为你想扩容的长度,或者你想缩容的长度,然后再用一次for循环对短数组进行一次遍历,在逐个将原数组的元素赋值给新数组,这样一来,就完成了我们所谓的扩容或者缩容操作,我们感知上我们的数组扩大了,其实扩大之后的数组已经成为了另一个数组,在之后,若原数组,再也没被引用的情况下,原数组在堆内存中占用的空间将由java中的垃圾处理机制,对原数组进行清理,清空所有的值,并将开辟的空间清空;
哈希表|散列表()
常见的异常合集
//OutOfMemoryError
堆内存溢出(存对象的地方) 数组大小过大
//StackOverFlowError
栈内存溢出(函数运行时出现的问题)
//java.lang.NullPointerException
这个异常都是因为调用null对象的方法,就是一个对象还没有正常的出事话,就先调用它的方法,比如 Object obj=null; obj.toString();这就会抛出这个异常;
对一维无序数组的排序方法
(1)冒泡排序
思路:首先需要两个嵌套的for循环,外层的for循环控制轮数,i同时也代表指针所在位置,内存的for循环则控制每轮比较的次数,j同时也代表指针所在位置.
外部循环首指针指向第i个元素,同时整体外部循环控制轮数,内部循环首指针指向第i+1个元素,排序过程中始终为当前元素与其后一个元素进行比较,第i个元素如果大于第i+1个元素,则交换位置,否则两元素相对位置不变,以此思路比完一轮,即可知末尾元素应为最大元素,此时外部控制循环轮数减1,内部循环控制比较次数同时减一,即可知倒数第二位的元素为倒数第二大的元素,依次进行比较并且内部交换,当所有轮数进行比较完之后,自然而然会给出无序数组从小到大的排列方式;
时间复杂度:采用双层for循环,时间复杂度为O(n^2)
比较方式:每一个数字都要和其他数字比较一下
冒泡排序的代码实现
import java.util.Arrays;
class BubbleSort{
public static void main(String[] args){
int[] a={6,4,9,1,8,3,2,7,5};
for(int i=0;i<a.length-1;i++){
for(int j=0;j<a.length-1-i;j++){
if(a[j]>a[j+1]){
swap(a,j,j+1);
}
}
}
System.out.println(Arrays.toString(a));
}
public static void swap(int[] a,int i,int j){
int temp=a[i];
a[i]=a[j];
a[j]=temp;
//+-+
//^^^
}
}
(2)选择排序
思路:首先需要两个嵌套的for循环,外层的for循环控制轮数,i同时也代表指针所在位置,内存的for循环则控制每轮比较的次数,j同时也代表指针所在位置.
外部循环首指针指向第i个元素,同时整体外部循环控制轮数,内部循环首指针指向第i+1个元素,排序过程中始终为当前元素与i+1(j)之后的所有元素进行比较,如果第j个元素如果小于第i个元素,则交换位置,否则两元素相对位置不变,以此思路比完一轮,即可知首位元素应为最小元素,此时外部控制循环轮数减1,内部循环控制比较次数同时减一,即可知正数第二位的元素为倒数第二小的元素,依次进行比较并且内部交换,当所有轮数进行比较完之后,自然而然会给出无序数组从小到大的排列方式;
时间复杂度:采用双层for循环,时间复杂度为O(n^2)
比较方式:每一个元素都要和其他元素进行比较
选择排序的代码实现
import java.util.Arrays;
class SelectSort{
public static void main(String[] args){
int[] a={6,4,9,1,8,3,2,7,5};
for(int i=0;i<a.length-1;i++){
for(int j=i+1;j<a.length;j++){
if(a[i]>a[j]){
swap(a,i,j);
}
}
}
System.out.println(Arrays.toString(a));
}
public static void swap(int[] a,int i,int j){
int temp=a[i];
a[i]=a[j];
a[j]=temp;
//+-+
//^^^
}
}
(3)插入排序
思路:将数组的第一个数认为是有序数组,从后往前(从前往后)扫描该有序数组,把数组中其余n-1个数,根据数值的大小, 插入到有序数组中,直至数组中的所有数有序排列为止。这样的话,n个元素需要进行n-1轮排序!
(1)外层循环表示的是排序的趟数,n个数字需要n-1趟,因此,外层循环的次数是n-1次;同时也代表数的位置。
(2)内层循环表示的是每一趟排序的数字。根据插入排序的思想,第i趟排序时,有序数组中的数字就有i个,就需要进行i次比较,因此循环i次。注意采用的是从后往前进行比较。
举个例子:4个数字4,6,7,5进行从大到小的排序。前插排序法具体过程如下:
把第一个数4插入到空的有序数组中的第一个位置上,得到新数字序列4;
第一趟:从后往前扫描有序数组,将第二个数字6和有序数组中的4进行比较,6大于4,此时将4后移一个位置。此时已经扫描完有序数组中的数,将6插入到4的前面(有序数组的第一个位置),得到新数字序列6,4;
第二趟:从后往前扫描有序数组,先将第三个数字7和有序数组中的4进行比较,7大于4,此时将4后移一个位置;再将7和有序数组中的6进行比较,7大于6,此时将6后移一个位置。此时已经扫描完有序数组中的数,将7插入到6的前面(有序数组的第一个位置),得到新数字序列7,6,4;
第三趟:从后往前扫描有序数组,先将第四个数字5和有序数组中的4进行比较,5大于4,此时将4后移一个位置;再将5和有序数组中的6进行比较,5小于6,由于有序数组就按照从大到小排列的,此时直接把5插入到4的前面即可!不需要再和7进行比较!最后,得到新数字序列7,6,5,4;
时间复杂度:采用双层for循环,时间复杂度为O(n^2)
比较方式:并不是每个元素和其他元素进行比较;如果左边的数字比当前小,意味着左边一切都比它小且有序
插入排序的代码实现
import java.util.Arrays;
class InsertSort{
public static void main(String[] args){
int[] a={6,4,9,1,8,3,2,7,5};
for(int i=1;i<a.length;i++){
int e=a[i];
int j=i;
while(j>0&&a[j-1]>e){
a[j]=a[j-1];
j--;
}
a[j]=e;
}
System.out.println(Arrays.toString(a));
}
public static void swap(int[] a,int i,int j){
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
二维数组
(1)声明二维数组的语法:
数据类型 [ ] [ ] 数组名 ;
或者
数据类型 数组名 [ ] [ ] ;//允许这种方式,但并不推荐使用
(2)实质:二维数组的实质其实是一个的数组,它的每个元素是一个一维数组;第一维代表行数,同时也代表为行在堆内存中开辟的空间;第二维代表列数,即每一行中有多少个元素,同时代表为列在堆内存中开辟的空间;
(3)获取长度的方式:假设创建一个二维数组 int [ ][ ] arr = new int [10] [10];
arr.length 实际上是获取元素数,也可以理解为行数
arr[i].length 实际上是获取每个元素中具体的个数,也可以理解为列数
经典五子棋(无图形化界面)的代码实现
import java.util.Scanner;
class WuZiQi{
/*
1.创建一个棋盘
2.对棋盘进行初始化
3.打印棋盘
4.开始游戏
*/
//1.
public static String[][] board=null;
public static Scanner scanner=new Scanner(System.in);
public static void main(String[] args){
//2.
initBoard();
//3.
printBoard();
//4.
startGame();
}
public static void startGame(){
int player=0;
while(!isGameOver()){
if(player%2==0){//黑方
System.out.println(">>>黑方下棋:");
if(!xiaqi("O")){
continue;
}
}else{//白方
System.out.println(">>>白方下棋:");
if(!xiaqi("X")){
continue;
}
}
player++;
}
System.out.println(">>>游戏结束!!");
}
public static boolean isGameOver(){
for(int i=0;i<board.length;i++){
for(int j=0;j<board.length;j++){
if(!board[i][j].equals("+")){
//向右
if(j<11){
boolean flag=true;
for(int dy=1;dy<=4;dy++){
if(board[i][j]!=board[i][j+dy]){
flag=false;
break;
}
}
if(flag){
return true;
}
}
//向下
if(i<11){
boolean flag=true;
for(int dx=1;dx<=4;dx++){
if(board[i][j]!=board[i+dx][j]){
flag=false;
break;
}
}
if(flag){
return true;
}
}
//右下
if(i<11&&j<11){
boolean flag=true;
for(int d=1;d<=4;d++){
if(board[i][j]!=board[i+d][j+d]){
flag=false;
break;
}
}
if(flag){
return true;
}
}
//右上
if(i>3&&j<11){
boolean flag=true;
for(int d=1;d<=4;d++){
if(board[i][j]!=board[i-d][j+d]){
flag=false;
break;
}
}
if(flag){
return true;
}
}
}
}
}
return false;
}
public static boolean xiaqi(String chess){
System.out.print(">>>请输入x坐标:");
int x=scanner.nextInt()-1;
System.out.print(">>>请输入y坐标:");
int y=scanner.nextInt()-1;
if(board[x][y].equals("+")){
board[x][y]=chess;
printBoard();
return true;
}else{
System.out.println(">>>棋子已存在,请重新下棋!");
return false;
}
}
public static void printBoard(){ //打印棋盘
System.out.print(" ");
for(int i=1;i<=15;i++){
System.out.printf("%-3d",i); //打印纵坐标,并让格式化输出
}
System.out.println();
for(int i=0;i<board.length;i++){
System.out.printf("%-3d",i+1); //打印横坐标,并进行格式化输出
for(int j=0;j<board[i].length;j++){
System.out.print(board[i][j]+" "); //将刚才已进行初始化填充的棋盘打印出来
}
System.out.println(); //每打印一行棋,进行换行
}
}
public static void initBoard(){ //初始化棋盘
board=new String[15][15]; //为二维型字符串数组开辟空间为15*15
for(int i=0;i<board.length;i++){
for(int j=0;j<board[i].length;j++){
board[i][j]="+"; //棋盘的每一个坐标的初始化填充
}
}
}
}
经典猜字符代码实现
import java.util.*;
class Class34{
//1.先生成一组单词
public static String[] words={"computer","since","datastruct","banana","sasuke","naruto","jiraya","hasake"};
//2.随机抽取一个单词
public static String word=null; //主函数外初始化word字符,全局调用
//3.创建该单词的一个状态数组
public static boolean[] state=null; //主函数外初始化与抽出word字符相对应的状态数组,全局调用
//4.当前轮猜错的次数
public static int missed=0; //主函数外初始化并进行赋值初始化猜错次数,全局调用
public static void main(String[] args){ //主函数中写具体实现方法,细节实现可写在自定义函数内,即可以避免代码冗余的同时逻辑结构也变得清晰起来
Scanner scanner=new Scanner(System.in); //初始化scanner方法
Random random=new Random(); //初始化random方法
word=words[random.nextInt(words.length)];
state=new boolean[word.length()];
//5.开始输入字符猜单词
while(true){
String password=getPassWord();
System.out.print("Enter a letter in word "+password+":");
String letter=scanner.nextLine();
changeWordState(letter);
if(isEnd()){
System.out.println("The word is "+word+".You missed "+missed+" time");
System.out.print("Do you want to guess another word?Enter y or n:");
if(scanner.nextLine().equals("y")){
word=words[random.nextInt(words.length)];
state=new boolean[word.length()];
missed=0;
}else{
break;
}
}
}
}
public static boolean isEnd(){
for(int i=0;i<state.length;i++){
if(state[i]==false){
return false;
}
}
return true;
}
public static void changeWordState(String letter){
boolean isExist=false;
for(int i=0;i<word.length();i++){
if((word.charAt(i)+"").equals(letter)){
isExist=true;
if(state[i]==false){
state[i]=true;
}else{
System.out.println("\t"+letter+" is already in the word");
return;
}
}
}
if(!isExist){
missed++;
System.out.println("\t"+letter+" is not in the word");
}
}
public static String getPassWord(){
String password="";
for(int i=0;i<word.length();i++){
if(state[i]==true){
password+=word.charAt(i);
}else{
password+="*";
}
}
return password;
}
}
资源链接:https://blog.csdn.net/weixin_43956598/article/details/90181567 (插入排序的具体实现细节)