数据类型
-
基本数据类型
- 数值型
- 整数类型:byte、short、int、long
- 浮点类型:float、double
- 字符型:char
- 布尔型:boolean
- 数值型
-
引用数据类型
-
类
-
接口
-
数组
-
不同的数值型运算时,优先级为:
byte、char、short < int < long < float < double
当byte、char、short三种类型的变量做运算时,结果为int
运算符
-
算术运算符:+ - * / % ++ –
-
赋值运算符:= += -= *= /= %=
-
比较运算符:== != > >= < <= instanceof
-
逻辑运算符:& && | || !
&与&&的区别:当左边为错误时,&会执行右边的式子,而&&不会执行(|与||同理)
-
位运算符:<< (*2) >> (/2) >>>(无符号右移) &(按位与) |(按位或) ^(按位异或) ~(按位取反)
-
三元运算符:(条件表达式)?表达式1:表达式2
流程控制
- 分支结构
- if else switch
- 循环结构
- for
- while
- break
- continue
数组
特点:
- 按下标0开始
- 数组的元素,既可以是基本数据类型,也可以是引用数据类型
- 创建数组对象会在内存中开辟一整块连续的空间
- 数组的长度一旦确定,就不能修改
一维数组默认初始值
- 整型 int[] 0
- 浮点型 double[] 0.0
- 字符序 char[] 0或’\u0000’
- 布尔型 boolean[] false
查找
顺序查找(线性查找)
特点:通过数组下标递增来顺序扫描每个元素
public static int linearSearch(int[] arr,int key){
for (int i = 0; i < arr.length; ++i) {
if(arr[i] == key){
return i;
}
}
return -1;
}
折半查找(有序)
public static int binarySearch(int[] arr,int key){
int low = 0,high = arr.length - 1,mid;
while (low <= high){
mid = (low + high) / 2;
if(arr[mid] == key){
return mid;
}else if(arr[mid] > key){
high = mid - 1;
}else{
low = mid + 1;
}
}
return -1;
}
分块查找
思想:将查找表分为若干子块,块内无序,块间有序。即第一个块内的最大关键字小于第二个块内所有的关键字,吸收了顺序查找和折半查找各自的优点。
B树
多路平衡查找树,B树中所有结点的孩子个数的最大值称为B树的阶,比如五阶查找树每个结点最多有4个关键字,5个分支
- B树的特点:
- 每个结点最多有m棵子树(分支),最多含有m-1个关键字
- 若根节点不是终端结点(有孩子),则至少有两棵子树
- 除根结点外的所有非叶结点至少有⌈m/2⌉棵子树,即至少含有⌈m/2⌉ - 1个关键字,即五阶B树的非叶结点至少有3个子树,至少有2个关键字
- B树的查找分两步
- 首先查找节点,由于B树通常是在磁盘上存储的所以这步需要进行磁盘IO操作。
- 第二步是查找关键字,当找到某个节点后将该节点读入内存中然后通过顺序或者折半查找来查找关键字。若没有找到关键字,则需要判断大小来找到合适的分支继续查找。
B+树
一棵m阶B+树的特点:
- 每个分支结点最多有m棵子树(孩子结点)
- 非叶根结点(有孩子)至少有两棵子树,其他每个分支结点至少有⌈m/2⌉棵子树
- 结点中的子树个数和关键字个数相等
- 所有叶结点包含全部关键字及指向相应记录的指针,叶结点中将关键字按大小顺序排序,并且相邻叶结点按大小顺序相互链接起来
- 所有分支结点(非叶结点)中仅包含它的各个子结点(下一级的索引块)中关键字的最大值及指向其子结点的指针
散列表
思想:以数据对象的关键字key为自变量,通过一个确定的函数关系h,计算出对应的函数值h(key),把这个值解释为数据对象的存储地址,并按此存放,即“存储位置=h(key)”。
排序
插入排序
-
直接插入 时间:O(n)~O(n^2) 空间:O(1) 稳定性:稳定
特点:前有序,最好时间复杂度是O(n) 1 2 3 4
public static void insertSort(int[] arr){ int j = 0; int temp = 0; for (int i = 1; i < arr.length; i++) { if(arr[i] < arr[i - 1]){ temp = arr[i]; for (j = i - 1; j >= 0 ; --j) { if(arr[j] > temp){ arr[j + 1] = arr[j]; }else{ break; } } arr[j + 1] = temp; } } }
折半插入 时间:O(n)~O(n^2) 空间:O(1) 稳定性:稳定
特点:用折半查找找到插入的位置,再依次向后移动元素
public static void bisearchSort(int[] arr){ int temp = 0; int low,high,mid; for (int i = 1; i < arr.length; i++) { temp = arr[i]; low = 0; high = i - 1; while (low <= high){ mid = (low + high) / 2; if(arr[mid] > temp){ high = mid - 1; }else{ low = mid + 1; } }//最后一定是high在左,low在右,low指向正确的插入位置 //依次移动low右边的元素 for (int j = i - 1; j >= low ; --j) { arr[j + 1] = arr[j]; } arr[low] = temp; } }
-
希尔排序(缩小增量排序) 时间:O(n)~O(n^2) 空间:O(1) 稳定性:不稳定
特点:依次比较隔着一半长度(增量)的距离的元素,增量依次减小,隔着1/4长度,比较的元素变多
public static void shellSort(int[] arr){ int j,temp; int len = arr.length; for (int d = len / 2; d >= 1 ; d /= 2) { for (int i = d; i < len ; ++i) { if(arr[i] < arr[i - d]){ temp = arr[i];//把较小的数存起来 for (j = i - d; j >= 0 && arr[j] > temp; j -= d) { arr[j + d] = arr[j]; } arr[j + d] = temp; } } } }
交换排序
-
冒泡排序 时间:O(n)~O(n^2) 空间:O(1) 稳定性:稳定
特点:总共的趟数是length - 1,从后两个开始比较,依次往前比较,冒下一趟,最后不用再比第一个元素了
public static void bubbleSort(int[] arr){ int temp; boolean flag;//1,2,3,4 前几趟就已经有序了,没必要重复比较 for (int i = 0; i < arr.length - 1; ++i) {//比较 length - 1次 flag = true; for (int j = arr.length - 1; j > i; --j) {//从后依次向前比较 if(arr[j - 1] > arr[j]){ temp = arr[j]; arr[j] = arr[j - 1]; arr[j - 1] = temp; flag = false; } } if(flag){ break; } } }
-
快速排序 时间:O(nlogn)~O(n^2) 空间:O(nlogn) 稳定性:不稳定
public static void quickSort(int[] arr,int low,int high){ if(low < high){ int pivotpos = partition(arr,low,high); quickSort(arr,low,pivotpos - 1); quickSort(arr,pivotpos + 1,high); } } public static int partition(int[] arr,int low,int high){ int pivot = arr[low]; while (low < high){ while (low < high && arr[high] >= pivot){ --high; } arr[low] = arr[high]; while (low < high && arr[low] <= pivot){ ++low; } arr[high] = arr[low]; } arr[low] = pivot; return low; }
选择排序
-
简单选择排序 时间:O(n)~O(n^2) 空间:O(1) 稳定性:不稳定
特点:n个中选最小的放在第一个,剩下的n-1个选最小的放第二个,直到最后剩下一个,所以n-1次循环
public static void selectSort(int[] arr){ int temp; int min; for (int i = 0; i < arr.length - 1; ++i) { min = i; for (int j = i + 1; j < arr.length; ++j) { if(arr[j] < arr[min]){ min = j; } } if(min != i){ temp = arr[min]; arr[min] = arr[i]; arr[i] = temp; } } }
-
堆排序(大根堆) 时间:O(nlogn) 建堆时间:O(n) n-1次元素下坠 空间:O(1) 稳定性:不稳定
特点:左右孩子都比根结点要小 ,大根堆:arr[i] >= arr[2i + 1] (左孩子) && arr[i] >= arr[2i + 2] (右孩子)
小根堆:arr[i] <= arr[2i + 1] && arr[i] <= arr[2i + 2]
public static void adjustHeap(int[] arr,int k,int len){//长度这个参数必须有,堆低堆顶交换后,就没必要把最后一个元素也算上,交换后长度应该-- int temp = arr[k];//传进来的k为根结点 for (int i = 2 * k + 1; i < len ; i = i * 2 + 1) {//沿关键字较大的孩子结点向下筛选 if(i + 1 < len && arr[i] < arr[i + 1]){//i + 1 < arr.length 防止数组越界,不存在右孩子 i++; } if(temp >= arr[i]){ break; }else { arr[k] = arr[i];//左右孩子较大的那个换给根结点 k = i;//记录换的是哪个孩子 } } arr[k] = temp; } public static void heapSort(int[] arr){ int temp; //构建大根堆 for (int i = arr.length / 2 - 1; i >= 0 ; --i) { adjustHeap(arr,i,arr.length); } //调整堆结构,交换堆顶元素与末尾元素 for (int i = arr.length - 1; i > 0 ; --i) { temp = arr[0];//堆顶存起来(大数) arr[0] = arr[i]; arr[i] = temp; adjustHeap(arr,0,i); } }
归并排序
时间:O(nlogn) 空间:O(n) 稳定性:稳定
特点:对半分,8分4 左4分2 左2排序,右2排序,左4排序,右4分2,左2排序,右2排序,右4排序,整体8排序
public static void merge(int[] arr,int low,int mid,int high){
int[] arrTemp = new int[arr.length];//只有最后整体排序才用到总的长度,最小的2排序,只占用1个单位
int i = low;//左数组第一个元素索引
int j = mid + 1;//右数组订元素索引
int k = 0;//临时数组的索引
while (i <= mid && j <= high){
if(arr[i] <= arr[j]){
arrTemp[k++] = arr[i++];
}else{
arrTemp[k++] = arr[j++];
}
}
while (i <= mid){
arrTemp[k++] = arr[i++];
}
while (j <= mid){//如果是按顺序排序,例如1,2 右数组就不需要移动,直接按原来的位置赋值
arrTemp[k++] = arr[j++];
}
for (int l = 0; l < k; ++l) {
arr[low + l] = arrTemp[l];
}
}
public static void mergeSort(int[] arr,int low,int high){
if(low < high){
int mid = (low + high) / 2;//从中间划分
mergeSort(arr,low,mid);//对左半部分归并排序
mergeSort(arr,mid + 1,high);//对右半部分归并排序
merge(arr,low,mid,high);//归并
}
}
基数排序
基于内容排序
时间:O(d(n + r)) 空间:O(d(n + r)) 稳定性:稳定
数组常见异常
- ArrayIndexOutOfBoundsException
- NullPointerException
命名规范
- 包名:所有字母都小写
- 类名、接口名:大驼峰
- 变量名:名词 小驼峰
- 方法名:动词 小驼峰
- 常量名:所有字母都大写