链表和SpringBean流程图

master
kn5886348135 3 years ago
parent 228bd5aef9
commit 11adcc341e

@ -1,34 +1,34 @@
一个数的相反数为取反加1.
取反的结果和原来的数相加结果为2^32^-1,再加1则进位为0。
2^32^-1二进制为
```shell
11111111 11111111 11111111 11111111
```
```shell
# 例如 int a = 1024;二进制为
00000000 00000000 00001000 00000000
# 取反后
11111111 11111111 11110111 11111111
# 相加为
11111111 11111111 11111111 11111111
a+~a+1=0;则-a=~a+1;
```
```Java
# 打印int类型二进制字符串方法
private static void printCompleteBinaryStr(int num){
for (int i = 31; i >= 0; i--) {
System.out.print((num & (1 << i)) == 0 ? "0" : "1");
if (i < 31 && (i + 1) % 8 == 0) {
System.out.print(" ");
}
}
System.out.println();
}
```
Integer.MIN_VALUE取反加一后仍然为Integer.MIN_VALUE这不是bug。
Integer.MAX_VALUE加1后溢出为Integer.MIN_VALUEInteger.MIN_VALUE减一则溢出为Integer.MAX_VALUE。
一个数的相反数为取反加1.
取反的结果和原来的数相加结果为2^32^-1,再加1则进位为0。
2^32^-1二进制为
```shell
11111111 11111111 11111111 11111111
```
```shell
# 例如 int a = 1024;二进制为
00000000 00000000 00001000 00000000
# 取反后
11111111 11111111 11110111 11111111
# 相加为
11111111 11111111 11111111 11111111
a+~a+1=0;则-a=~a+1;
```
```Java
# 打印int类型二进制字符串方法
private static void printCompleteBinaryStr(int num){
for (int i = 31; i >= 0; i--) {
System.out.print((num & (1 << i)) == 0 ? "0" : "1");
if (i < 31 && (i + 1) % 8 == 0) {
System.out.print(" ");
}
}
System.out.println();
}
```
Integer.MIN_VALUE取反加一后仍然为Integer.MIN_VALUE这不是bug。
Integer.MAX_VALUE加1后溢出为Integer.MIN_VALUEInteger.MIN_VALUE减一则溢出为Integer.MAX_VALUE。

@ -1,94 +1,94 @@
# 算法的5个特点
1.有穷性
2.确定性(确定的执行流程或者确定的尝试流程)
3.可行性
4.输入
5.输出
# 选择排序
双层循环内层循环完成后获取最小值内层循环每次将最小值放到i位置。
0-i之间认为是有序i-n之间是原始数据从i-n之间选择最小的元素放到index为i的地方。
不稳定的排序
```Java
private static void selectionSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
int length = arr.length;
int tmp;
for (int i = 0; i < length; i++) {
int index = i;
for (int j = i; j < length; j++) {
// 小于号避免位置交换
index = arr[j] < arr[index] ? j : index;
}
if (index == i) {
continue;
}
tmp = arr[i];
arr[i] = arr[index];
arr[index] = tmp;
}
}
```
# 冒泡排序
双层循环,内层循环两两交换,内层循环完成后将最大值冒泡到最右边。
外层循环index从大到小内层循环index从小到大。
稳定排序
```Java
private static void bubbleSort(int[] arr){
int length = arr.length;
if (arr == null || length < 2) {
return;
}
int tmp;
for (int i = length - 1; i >= 0; i--) {
for (int j = 0; j < i; j++) {
if (arr[j + 1] < arr[j]) {
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
```
# 插入排序
每次获取原始数据最前面的那个元素交换到左侧已经有序的数组。
双层循环外层循环每次递增并获取i内层循环使用i挨个和0-1的数据比较并交换。如果i比i-1大或者内层循环到了最左侧则终止循环。
稳定排序
```Java
private static void insertSort(int[] arr){
int length = arr.length;
if (arr == null || length < 2) {
return;
}
int tmp;
for (int i = 0; i < length; i++) {
for (int j = i; j > 0; j--) {
if (arr[j - 1] > arr[j]) {
tmp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = tmp;
} else {
break;
}
}
}
}
```
# 算法的5个特点
1.有穷性
2.确定性(确定的执行流程或者确定的尝试流程)
3.可行性
4.输入
5.输出
# 选择排序
双层循环内层循环完成后获取最小值内层循环每次将最小值放到i位置。
0-i之间认为是有序i-n之间是原始数据从i-n之间选择最小的元素放到index为i的地方。
不稳定的排序
```Java
private static void selectionSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
int length = arr.length;
int tmp;
for (int i = 0; i < length; i++) {
int index = i;
for (int j = i; j < length; j++) {
// 小于号避免位置交换
index = arr[j] < arr[index] ? j : index;
}
if (index == i) {
continue;
}
tmp = arr[i];
arr[i] = arr[index];
arr[index] = tmp;
}
}
```
# 冒泡排序
双层循环,内层循环两两交换,内层循环完成后将最大值冒泡到最右边。
外层循环index从大到小内层循环index从小到大。
稳定排序
```Java
private static void bubbleSort(int[] arr){
int length = arr.length;
if (arr == null || length < 2) {
return;
}
int tmp;
for (int i = length - 1; i >= 0; i--) {
for (int j = 0; j < i; j++) {
if (arr[j + 1] < arr[j]) {
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
```
# 插入排序
每次获取原始数据最前面的那个元素交换到左侧已经有序的数组。
双层循环外层循环每次递增并获取i内层循环使用i挨个和0-1的数据比较并交换。如果i比i-1大或者内层循环到了最左侧则终止循环。
稳定排序
```Java
private static void insertSort(int[] arr){
int length = arr.length;
if (arr == null || length < 2) {
return;
}
int tmp;
for (int i = 0; i < length; i++) {
for (int j = i; j > 0; j--) {
if (arr[j - 1] > arr[j]) {
tmp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = tmp;
} else {
break;
}
}
}
}
```

@ -0,0 +1,56 @@
#### 单链表反转
使用while循环保存next节点设置当前节点的next保存pre移动head最后返回pre
```Java
private static Node reverseLinkedList(Node head) {
Node pre = null;
Node next = null;
while (head != null) {
next = head.getNext();
head.setNext(pre);
pre = head;
head = next;
}
return pre;
}
```
#### 双链表反转
使用while循环保存next节点设置当前节点的last和pre保存pre移动head最后返回pre
```Java
private static Node reverDoubleLinkedList(Node head) {
Node pre = null;
Node next = null;
while (head != null) {
next = head.getLast();
head.setLast(pre);
head.setPre(next);
pre = head;
head = next;
}
return pre;
}
```
单链表实现队列和栈
### 使用双链表实现双端队列
单链表和双链表的新增、删除,主要注意处理好前驱和后继指针,必要的时候添加中间变量保存。双链表注意处理头尾重合、为空的边界条件。
#### K个节点的组内逆序调整 LeetCode25
#### 两个链表相加 LeetCode2、LeetCode445
根据链表长度分三段处理,第一段处理短链表,第二段处理长链表多出的部分,第三段处理长链表最后的进位
#### 合并两个有序链表 LeetCode21
### 位图
位图的功能
位图的好处
位图的用法

@ -1,326 +0,0 @@
单链表反转
使用while循环保存next节点设置当前节点的next保存pre移动head最后返回pre
```Java
private static Node reverseLinkedList(Node head) {
Node pre = null;
Node next = null;
while (head != null) {
next = head.getNext();
head.setNext(pre);
pre = head;
head = next;
}
return pre;
}
```
双链表反转
使用while循环保存next节点设置当前节点的last和pre保存pre移动head最后返回pre
```Java
private static Node reverDoubleLinkedList(Node head) {
Node pre = null;
Node next = null;
while (head != null) {
next = head.getLast();
head.setLast(pre);
head.setPre(next);
pre = head;
head = next;
}
return pre;
}
```
单链表实现队列和栈
```Java
public class CustomQueue<V> {
private Node<V> head;
private Node<V> tail;
private int size;
public boolean isEmpty(){
return size == 0;
}
public void offer(V value) {
Node<V> node = new Node<>(value);
if (tail == null) {
head = node;
tail = node;
} else {
tail.setNext(node);
tail = node;
}
size++;
}
public V poll(){
if (head == null) {
return null;
}
V ans = head.getValue();
head = head.getNext();
size--;
return ans;
}
public V peek() {
if (head == null) {
return null;
}
return head.getValue();
}
private class Node<V> {
private V value;
private Node<V> next;
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
public Node<V> getNext() {
return next;
}
public void setNext(Node<V> next) {
this.next = next;
}
public Node(V value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node<?> node = (Node<?>) o;
return value.equals(node.value) &&
next.equals(node.next);
}
@Override
public int hashCode() {
return Objects.hash(value, next);
}
}
}
```
```Java
public class CustomStack<V> {
private Node<V> head;
private int size;
public boolean isEmpty(){
return size == 0;
}
public void push(V value){
Node<V> node = new Node<>(value);
if (head == null) {
head = node;
} else {
node.setNext(head);
head = node;
}
size++;
}
public V pop(){
if (head == null) {
return null;
}
V ans = null;
ans = head.getValue();
head.setNext(head.getNext());
size--;
return ans;
}
public V peek() {
return head == null ? null : head.getValue();
}
class Node<V>{
private V value;
private Node<V> next;
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
public Node<V> getNext() {
return next;
}
public void setNext(Node<V> next) {
this.next = next;
}
public Node(V value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node<?> node = (Node<?>) o;
return Objects.equals(value, node.value) &&
Objects.equals(next, node.next);
}
@Override
public int hashCode() {
return Objects.hash(value, next);
}
}
}
```
### 使用双链表实现双端队列
```Java
public class CustomDeque<V> {
private Node<V> head;
private Node<V> tail;
private int size;
public boolean isEmpty() {
return size == 0;
}
public void pushHead(V value){
Node<V> node = new Node<>(value);
if (head == null) {
head = node;
tail = node;
} else {
node.setLast(head);
head.setPre(node);
head = node;
}
size++;
}
public void pushTail(V value){
Node<V> node = new Node<>(value);
if (head == null) {
head = node;
tail = node;
} else {
tail.setLast(node);
node.setPre(tail);
tail = node;
}
size++;
}
public V pollHead(){
if (head == null) {
return null;
}
V ans = head.getValue();
if (head.equals(tail)) {
head = null;
tail = null;
} else {
head = head.getLast();
head.setPre(null);
}
size--;
return ans;
}
public V pollTail(){
if (tail == null) {
return null;
}
V ans = tail.getValue();
if (head.equals(tail)) {
head = null;
tail = null;
} else {
tail = tail.getPre();
tail.setLast(null);
}
size--;
return ans;
}
public V peekHead(){
return head == null ? null : head.getValue();
}
public V peekTail(){
return tail == null ? null : tail.getValue();
}
class Node<V>{
private V value;
private Node<V> last;
private Node<V> pre;
public Node(V value) {
this.value = value;
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
public Node<V> getLast() {
return last;
}
public void setLast(Node<V> last) {
this.last = last;
}
public Node<V> getPre() {
return pre;
}
public void setPre(Node<V> pre) {
this.pre = pre;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node<?> node = (Node<?>) o;
return Objects.equals(value, node.value);
}
@Override
public int hashCode() {
return Objects.hash(value);
}
}
}
```
单链表和双链表的新增、删除,主要注意处理好前驱和后继指针,必要的时候添加中间变量保存。双链表注意处理头尾重合、为空的边界条件。
K个节点的组内逆序调整

@ -0,0 +1,63 @@
## Spring启动流程
### prepareRefresh()
记录时间、active标记、获取environment(系统环境变量和System.setProperty()设置的)、初始化监听器和事件集合。
### obtainFreshBeanFactory()
关闭以前的BeanFactory创建一个新的BeanFactory供上下文生命周期的各阶段使用。
父beanDefinition、bean可覆盖、循环引用
loadBeanDefinitions()通过inputStream读取并解析xml文档拿到beanDefinition。
### prepareBeanFactory()
准备BeanFactory设置ClassLoader、SPEL解析器、propertyEditor、BeanPostProcessor(ApplicationContextAwareProcessor)、ignoreDependencyInterface(各种Aware接口)、registerResolvableDependency、BeanPostProcessor(ApplicationListenerDetector、environment单例。
### postProcessBeanFactory(beanFactory)
继承ClassPathXmlApplicationContext的子类可以修改beanFactory用于实现一些自定义的功能。
### invokeBeanFactoryPostProcessors(beanFactory)
BeanDefinitionRegistryPostProcessors和BeanFactoryPostProcessors按照实现PriorityOrdered、Ordered接口、没有实现这两个接口的PostProcessors处理执行顺序@Order注解在这里是不考虑的。
// Register bean processors that intercept bean creation.
### registerBeanPostProcessors(beanFactory)
BeanPostProcessor按照实现PriorityOrdered、Ordered接口、没有实现这两个接口的PostProcessors处理执行顺序@Order注解在这里是不考虑的。
BeanPostProcessorChecker用来记录日志。
### initMessageSource()
初始化MessageSource<font color=red>MessageSource是格式化字符串的?</font>
### initApplicationEventMulticaster()
初始化应用事件监听器SimpleApplicationEventMulticaster通过线程池往各种监听器添加事件。
### onRefresh()
由子类实现比如Spring Boot创建web server。
### registerListeners()
注册所有实现了ApplicationListener接口的监听器并发布早起应用事件。
### finishBeanFactoryInitialization(beanFactory)
实例化所有非懒加载的单例。
ConversionService(转换系统的一个入口,<font color=red>可用于常见的日期格式转换?</font>)、添加EmbeddedValueResolver、BeanFactory方式获取LoadTimeWeaverAware、置空temporary ClassLoader、冻结配置、预实例化单例。
preInstantiateSingletons()
遍历beanNames触发所有非懒加载bean实例化。
遍历beanNames触发所有适用 bean 的初始化后回调。
getBean(beanName) -> doGetBean -> getSingleton(三级缓存) -> createBean -> doCreateBean -> 代理和反射创建bean(三级缓存) -> populateBean -> initializeBean
### finishRefresh()
清理资源缓存、初始化LifecycleProcessor、发布最终事件
### resetCommonCaches()
### contextRefresh.end()

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Loading…
Cancel
Save