1.数据结构
1.1数组
1.2链表
1.2.1 面试
(1)如何实现链表的反转?
答:使用头节点插入法。
1) 创建一个带头节点的链表
2) 定义一个循环链表变量p,p的初始值为待反转的链表
3) 遍历待反转的链表,遍历条件为 (p !=null)
a. 定义一个临时链表变量tempList保存p->next的值(因为p->next值会改变),用于下一次循环。
b. 把p当前指向的首节点和resultList链表的头节点之后的节点拼接起来。
c. 把b.步骤中拼接的节点 再拼接到resultList头节点后。
d. p重新赋值为3.1步骤中保存的tempList的值。
4) 返回resultList->next.即反转后的链表。
1.3
2.基本排序算法
2.1 简介
常见的内部排序算法有:冒泡排序、选择排序、插入排序、希尔排序、快速排序、归并排序等。
2.2 代码实现
2.2.1 冒泡排序
中心思想:越大的元素会经由交换慢慢“浮”到数列的顶端。
一共进行数组的大小 - 1 次大的循环
每一趟排序的次数逐渐减少
算法描述:
1. 是通过每一次遍历获取最大/最小值
2. 将最大值/最小值放在尾部/头部
3. 然后除开最大值/最小值,剩下的数据进行遍历获取最大/最小值
例子:5,3,2,4,8
3,2,4,5,8
2,3,4,5,8
2,3,4,5,8
代码:
//基础冒泡
public static void main(String[] args) {
int arr[] = {8, 5, 3, 2, 4};
for (int i = 0; i < arr.length-1; i++) {
//外层循环,遍历次数
for (int j = 0; j < arr.length - i - 1; j++) {
//内层循环,升序(如果前一个值比后一个值大,则交换)
//内层循环一次,获取一个最大值
if (arr[j] > arr[j + 1]) {
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
//优化冒泡——加标志位
public static void main(String[] args) {
int arr[] = {8, 5, 3, 2, 4};
int temp = 0;
boolean flag = false;
for (int i = 0; i < arr.length-1; i++) {
//外层循环,遍历次数
for (int j = 0; j < arr.length - i - 1; j++) {
//升序(如果前一个值比后一个值大,则交换)
if (arr[j] > arr[j + 1]) {
flag = true;
temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
if (!flag){
break; //在一趟排序中,一次交换都没有发生过
}else {
flag = false; //重置flag,进行下次判断
}
}
}
System.out.println(Arrays.toString(arr));
}
2.2.2 选择排序
2.2.3 插入排序
2.2.4 希尔排序
2.2.5 归并排序
算法描述:
1) 归并排序是采用分治法的一个非常典型的应用。归并排序的思想就是先递归分解数组,再合并数组。
2) 将数组分解最小之后,然后合并两个有序数组
3) 基本思路是比较两个数组的最前面的数,谁小就先取谁,取了后相应的指针就往后移一位。
4) 然后再比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来即可。
代码:
public static void main(String[] args) {
int[] array = {2,1,4,3,5,1};
System.out.println(Arrays.toString(guibing(array)));
}
//归并排序 —— 一分为二,递归
private static int[] guibing(int[] array) {
if (array.length <2) return array;
int mid = array.length/2;
int[] left = Arrays.copyOfRange(array, 0, mid);
int[] right = Arrays.copyOfRange(array, mid, array.length);
return paixu(guibing(left), guibing(right));
}
//将两段排序好的数组合成一个排序好的数组
private static int[] paixu(int[] left, int[] right) {
int[] result = new int[left.length+right.length];
for (int index = 0, i = 0, j = 0; index < result.length; index++) {
//表示左边的数字已经完全填进去了,到达左边数组末尾了,然后直接把右边的数组copy进来就好了,因为已经排序了
if (i>=left.length)
result[index] = right[j++];
//表示右边的数字已经完全填进去了,到达右边数组的末尾了,然后直接把左边的数组copy进来就好了
else if (j>=right.length)
result[index] = left[i++];
//如果左边的数大于右边的数,则把右边的数填进去,指针向后移
else if (left[i]>right[j])
result[index] = right[j++];
//如果右边的数大于左边的数,则把左边的数填进去,指针向后移
else
result[index] = left[i++];
}
return result;
}
2.2.6 快速排序
算法描述:
1) 首先确定列表第一个数据为中间值,第一个值看成空缺(低指针空缺)。
2) 然后在剩下的队列中,看成有左右两个指针(高低)。
3) 开始高指针向左移动,如果遇到小于中间值的数据,则将这个数据赋值到低指针空缺,并且将高指针的数据看成空缺值(高指针空缺)。然后先向右移动一下低指针,并且切换低指针移动。
4) 当低指针移动到大于中间值的时候,赋值到高指针空缺的地方。然后先高指针向左移动,并且切换高指针移动。重复2)、3)操作。
5) 直到高指针和低指针相等时退出,并且将中间值赋值给对应相等指针位置。
6) 然后将中间值的左右两边看成行的列表,进行快速排序操作。
代码:
//快排
public static void main(String[] args) {
int arr[] = {7, 5, 3, 2, 4, 1, 8, 9, 6};
//快速排序
int low = 0;
int high = arr.length - 1;
quickSort(arr, low, high);
System.out.println(Arrays.toString(arr));
}
public static void quickSort(int[] arr, int low, int high) {
//如果指针在同一位置(只有一个数据时),退出
if (high - low < 1) {
return;
}
//标记,从高指针开始,还是低指针(默认高指针)
boolean flag = true;
//记录指针的其实位置
int start = low;
int end = high;
//默认中间值为低指针的第一个值
int midValue = arr[low];
while (true) {
//高指针移动
if (flag) {
//如果列表右方的数据大于中间值,则向左移动
if (arr[high] > midValue) {
high--;
} else if (arr[high] < midValue) {
//如果小于,则覆盖最开始的低指针值,并且移动低指针,标志位改成从低指针开始移动
arr[low] = arr[high];
low++;
flag = false;
}
} else {
//如果低指针数据小于中间值,则低指针向右移动
if (arr[low] < midValue) {
low++;
} else if (arr[low] > midValue) {
//如果低指针的值大于中间值,则覆盖高指针停留时的数据,并向左移动高指针。切换为高指针移动
arr[high] = arr[low];
high--;
flag = true;
}
}
//当两个指针的位置相同时,则找到了中间值的位置,并退出循环
if (low == high) {
arr[low] = midValue;
break;
}
}
//然后出现有,中间值左边的小于中间值。右边的大于中间值。
//然后在对左右两边的列表在进行快速排序
quickSort(arr, start, low -1);
quickSort(arr, low + 1, end);
}
// 左程云解法:
public static void main(String[] args) {
int[] arr = new int[]{6, 2, 3, 4, 5, 6};
quickSort(arr);
System.out.println(Arrays.toString(arr));
}
private static void quickSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
quickSort(arr, 0, arr.length - 1);
}
private static void quickSort(int[] arr, int l, int r) {
if (l < r) {
swap(arr, l + (int) (Math.random() * (r - l + 1)), r);
int[] p = partition(arr, l, r); // 存储中间值的左右边界
quickSort(arr, l, p[0] - 1);
quickSort(arr, p[1] + 1, r);
}
}
// 左边界 中间 右边界
private static int[] partition(int[] arr, int l, int r) {
int less = l - 1; // <区右边界
int more = r;// >区左边界
while (l < more) {
if (arr[l] < arr[r]) {
swap(arr, ++less, l++);
} else if (arr[l] > arr[r]) {
swap(arr, --more, l);
} else {
l++;
}
}
swap(arr, more, r);
return new int[]{less + 1, more};
}
public static void swap(int[] arr, int a, int b) {
// arr[a] = arr[a] ^ arr[b];
// arr[b] = arr[a] ^ arr[b];
// arr[a] = arr[a] ^ arr[b];
int temp;
temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}