归并排序

  1. 整体就是一个简单递归,左边排好序、右边排好序、让其整体有序

  2. 让其整体有序的过程里用了外排序方法

  3. 利用master公式来求解时间复杂度

  4. 归并排序的实质

时间复杂度0(N*logN),额外空间复杂度0(N)

JAVA

import java.util.Arrays;

public class MergeSort {

	public static void mergeSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
process(arr, 0, arr.length - 1);
} public static void process(int[] arr, int l, int r) {
if (l == r) {
return;
}
int mid = l + ((r - l) >> 1);
process(arr, l, mid);
process(arr, mid + 1, r);
merge(arr, l, mid, r);
} public static void merge(int[] arr, int l, int m, int r) {
int[] help = new int[r - l + 1];
int i = 0;
int p1 = l;
int p2 = m + 1;
while (p1 <= m && p2 <= r) {
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= m) {
help[i++] = arr[p1++];
}
while (p2 <= r) {
help[i++] = arr[p2++];
}
for (i = 0; i < help.length; i++) {
arr[l + i] = help[i];
}
}
}

C++

template <typename T> //向量归并排序
void Vector<T>::mergeSort ( Rank lo, Rank hi ) { //0 <= lo < hi <= size
if ( hi - lo < 2 ) return; //单元素区间自然有序,否则...
int mi = ( lo + hi ) / 2; //以中点为界
mergeSort ( lo, mi ); mergeSort ( mi, hi ); //分别排序
merge ( lo, mi, hi ); //归并
}
template <typename T> //有序向量(区间)的归并
//各自有序的子向量[lo, mi)和[mi, hi)
void Vector<T>::merge ( Rank lo, Rank mi, Rank hi ) { T* A = _elem + lo; //合并后的向量A[0, hi - lo) = _elem[lo, hi)
int lb = mi - lo; T* B = new T[lb]; //前子向量B[0, lb) = _elem[lo, mi) for ( Rank i = 0; i < lb; i++ )
B[i] = A[i]; //复制前子向量
int lc = hi - mi; T* C = _elem + mi; //后子向量C[0, lc) = _elem[mi, hi) //归并:反复从B和C首元素中取出更小者
for ( Rank i = 0, j = 0, k = 0; j < lb; )
A[i++] = ( lc <= k || B[j] <= C[k] ) ? B[j++] : C[k++]; //将其归入A中
delete [] B; //释放临时空间B
}//归并后得到完整的有序向量[lo, hi]

归并排序的扩展

小和问题和逆序对问题

小和问题

在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组 的小和。求一个数组的小和。

例子:[1,3,4,2,5] 1左边比1小的数,没有;3左边比3小的数,1; 4左 边比4小的数,1、3; 2左边比2小的数,1; 5左边比5小的数,1、3、4、 2;所以小和为1+1+3+1+1+3+4+2=16

1,3,4,2,5 求取右边有多少比该数大

4个1, 2个3,1个4, 1个2

public class SmallSum {

	public static int smallSum(int[] arr) {
if (arr == null || arr.length < 2) {
return 0;
}
return mergeSort(arr, 0, arr.length - 1);
} public static int mergeSort(int[] arr, int l, int r) {
if (l == r) {
return 0;
}
int mid = l + ((r - l) >> 1);
return mergeSort(arr, l, mid)
+ mergeSort(arr, mid + 1, r)
+ merge(arr, l, mid, r);
} public static int merge(int[] arr, int l, int m, int r) {
int[] help = new int[r - l + 1];
int i = 0;
int p1 = l;
int p2 = m + 1;
int res = 0;
while (p1 <= m && p2 <= r) {
res += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0;
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= m) {
help[i++] = arr[p1++];
}
while (p2 <= r) {
help[i++] = arr[p2++];
}
for (i = 0; i < help.length; i++) {
arr[l + i] = help[i];
}
return res;
}
}

逆序对问题

在一个数组中,左边的数如果比右边的数大,则折两个数 构成一个逆序对,请打印所有逆序对。

		public static void reverseOrder(int[] arr) {
if (arr==null || arr.length<2) {
return ;
}
mergeSort(arr,0,arr.length-1);
}
public static int mergeSort(int[] arr, int l, int r) {
if (l == r) {
return 0;
}
int mid = (l+r)/2;
int k = mergeSort(arr, l, mid)
+mergeSort(arr, mid+1, r)+merge(arr,l,mid,r);
System.out.println("merge总逆序数:"+k);
return k;
} public static int merge(int[] arr, int l, int mid, int r) {
int merge_res=0;
//help的长度不是一个大的N 而是每次分治的长度
int[] help = new int[r - l + 1];
int i=0;
int p1 = l;
int p2 = mid+1; while(p1 <= mid && p2 <= r) {
if ( arr[p2] < arr[p1] ) { //说明 p2 此时比p1中剩下的元素都小
merge_res += (mid-p1+1); //核心
}
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++] ;
}
while(p1<=mid) {
help[i++] = arr[p1++];
}
while (p2<=r) {
help[i++] = arr[p2++]; }
//拷贝到 arr数组
for (int j = 0; j < help.length; j++) {
arr[l+j] = help[j];
}
System.out.println("merge_res:"+merge_res);
return merge_res;
}

  1. 堆结构就是用数组实现的完全二叉树结构
  2. 完全二叉树中如果每棵子树的最大值都在顶部就是大根堆
  3. 完全二叉树中如果每棵子树的最小值都在顶部就是小根堆
  4. 堆结构的heapInsert与heapify操作
  5. 堆结构的增大和减少
  6. 优先级队列结构,就是堆结构
	// 某个数现在处在index位置,往上继续移动
public static void heapInsert(int[] arr, int index) {
while (arr[index] > arr[(index - 1) / 2]) {
swap(arr, index, (index - 1) / 2);
index = (index - 1) / 2;
}
} // 某个数在index位置,能否往下移动
public static void heapify(int[] arr, int index, int heapSize) {
int left = index * 2 + 1; // 左孩子的下标
while (left < heapSize) { // 下方还有孩子的时候
// 两个孩子中,谁的值大,把下标给largest
int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
// 父和较大的孩子之间,谁的值大,把下标给largest
largest = arr[largest] > arr[index] ? largest : index;
if (largest == index) {
break;
}
swap(arr, largest, index);
index = largest;
left = index * 2 + 1;
}
} public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}

堆排序

  1. 先让整个数组都变成大根堆结构,建立堆的过程:

  2. 从上到下的方法,时间复杂度为0(N*logN)

  3. 从下到上的方法,时间复杂度为0(N)

  4. 把堆的最大值和堆末尾的值交换,然后减少堆的大小之后,再去调整堆,一直周而复始,时间复杂度为0(N*log N)

  5. 堆的大小减小成0之后,排序完成

public static void heapSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int i = 0; i < arr.length; i++) {
heapInsert(arr, i); //O(logN)
}
int size = arr.length;
swap(arr, 0, --size);
while (size > 0) { //O(N)
heapify(arr, 0, size); //O(logN)
swap(arr, 0, --size);
}
}

C++实现堆

完全二叉堆

#define  Parent(i)   ( ( ( i ) - 1 ) >> 1 ) //PQ[i]的父节点(floor((i-1)/2),i无论正负)
#define LChild(i) ( 1 + ( ( i ) << 1 ) ) //PQ[i]的左孩子
#define RChild(i) ( ( 1 + ( i ) ) << 1 ) //PQ[i]的右孩子
#define InHeap(n, i) ( ( ( -1 ) < ( i ) ) && ( ( i ) < ( n ) ) ) //判断PQ[i]是否合法
#define LChildValid(n, i) InHeap( n, LChild( i ) ) //判断PQ[i]是否有一个(左)孩子
#define RChildValid(n, i) InHeap( n, RChild( i ) ) //判断PQ[i]是否有两个孩子
#define Bigger(PQ, i, j) ( lt( PQ[i], PQ[j] ) ? j : i ) //取大者(等时前者优先)
#define ProperParent(PQ, n, i) /*父子(至多)三者中的大者*/ \
( RChildValid(n, i) ? Bigger( PQ, Bigger( PQ, i, LChild(i) ), RChild(i) ) : \
( LChildValid(n, i) ? Bigger( PQ, i, LChild(i) ) : i ) \
) //相等时父节点优先,如此可避免不必要的交换

PQ_ComplHeap模拟类

Vector/Vector.h

typedef int Rank; //秩
#define DEFAULT_CAPACITY 3 //默认的初始容量(实际应用中可设置为更大) template <typename T> class Vector { //向量模板类
protected:
Rank _size; int _capacity; T* _elem; //规模、容量、数据区
void copyFrom ( T const* A, Rank lo, Rank hi ); //复制数组区间A[lo, hi)
void expand(); //空间不足时扩容
void shrink(); //装填因子过小时压缩
bool bubble ( Rank lo, Rank hi ); //扫描交换
void bubbleSort ( Rank lo, Rank hi ); //起泡排序算法
Rank max ( Rank lo, Rank hi ); //选取最大元素
void selectionSort ( Rank lo, Rank hi ); //选择排序算法
void merge ( Rank lo, Rank mi, Rank hi ); //归并算法
void mergeSort ( Rank lo, Rank hi ); //归并排序算法
void heapSort ( Rank lo, Rank hi ); //堆排序(稍后结合完全堆讲解)
Rank partition ( Rank lo, Rank hi ); //轴点构造算法
void quickSort ( Rank lo, Rank hi ); //快速排序算法
void shellSort ( Rank lo, Rank hi ); //希尔排序算法
public:
// 构造函数
//容量为c、规模为s、所有元素初始为v
Vector ( int c = DEFAULT_CAPACITY, int s = 0, T v = 0 )
{ _elem = new T[_capacity = c]; for ( _size = 0; _size < s; _elem[_size++] = v ); } //s<=c
Vector ( T const* A, Rank n ) { copyFrom ( A, 0, n ); } //数组整体复制
Vector ( T const* A, Rank lo, Rank hi ) { copyFrom ( A, lo, hi ); } //区间
Vector ( Vector<T> const& V ) { copyFrom ( V._elem, 0, V._size ); } //向量整体复制
//区间
Vector ( Vector<T> const& V, Rank lo, Rank hi ) { copyFrom ( V._elem, lo, hi ); }
// 析构函数
~Vector() { delete [] _elem; } //释放内部空间
// 只读访问接口
Rank size() const { return _size; } //规模
bool empty() const { return !_size; } //判空
Rank find ( T const& e ) const { return find ( e, 0, _size ); } //无序向量整体查找
Rank find ( T const& e, Rank lo, Rank hi ) const; //无序向量区间查找
Rank search ( T const& e ) const //有序向量整体查找
{ return ( 0 >= _size ) ? -1 : search ( e, 0, _size ); }
Rank search ( T const& e, Rank lo, Rank hi ) const; //有序向量区间查找
// 可写访问接口
T& operator[] ( Rank r ); //重载下标操作符,可以类似于数组形式引用各元素
const T& operator[] ( Rank r ) const; //仅限于做右值的重载版本
Vector<T> & operator= ( Vector<T> const& ); //重载赋值操作符,以便直接克隆向量
T remove ( Rank r ); //删除秩为r的元素
int remove ( Rank lo, Rank hi ); //删除秩在区间[lo, hi)之内的元素
Rank insert ( Rank r, T const& e ); //插入元素
Rank insert ( T const& e ) { return insert ( _size, e ); } //默认作为末元素插入
void sort ( Rank lo, Rank hi ); //对[lo, hi)排序
void sort() { sort ( 0, _size ); } //整体排序
void unsort ( Rank lo, Rank hi ); //对[lo, hi)置乱
void unsort() { unsort ( 0, _size ); } //整体置乱
int deduplicate(); //无序去重
int uniquify(); //有序去重
// 遍历
void traverse ( void (* ) ( T& ) ); //遍历(使用函数指针,只读或局部性修改)
template <typename VST> void traverse ( VST& ); //遍历(使用函数对象,可全局性修改)
}; //Vector

PQ/PQ.h

template <typename T> struct PQ { //优先级队列PQ模板类
virtual void insert ( T ) = 0; //按照比较器确定的优先级次序插入词条
virtual T getMax() = 0; //取出优先级最高的词条
virtual T delMax() = 0; //删除优先级最高的词条
};

完全二叉树接口

#include "Vector/Vector.h" //借助多重继承机制,基于向量
#include "PQ/PQ.h" //按照优先级队列ADT实现的
//完全二叉堆
template <typename T> struct PQ_ComplHeap : public PQ<T>, public Vector<T> {
PQ_ComplHeap() { } //默认构造
//批量构造
PQ_ComplHeap ( T* A, Rank n ) { copyFrom ( A, 0, n ); heapify ( _elem, n ); }
void insert ( T ); //按照比较器确定的优先级次序,插入词条
T getMax(); //读取优先级最高的词条
T delMax(); //删除优先级最高的词条
}; //PQ_ComplHeap
template <typename T> void heapify ( T* A, Rank n ); //Floyd建堆算法
template <typename T> Rank percolateDown ( T* A, Rank n, Rank i ); //下滤
template <typename T> Rank percolateUp ( T* A, Rank i ); //上滤

getMax

 //取优先级最高的词条
template <typename T> T PQ_ComplHeap<T>::getMax() { return _elem[0]; }

元素插入

算法

template <typename T> void PQ_ComplHeap<T>::insert ( T e ) { //将词条插入完全二叉堆中
Vector<T>::insert ( e ); //首先将新词条接至向量末尾
percolateUp ( _elem, _size - 1 ); //再对该词条实施上滤调整

上滤

//对向量中的第i个词条实施上滤操作,i < _size
template <typename T> Rank percolateUp ( T* A, Rank i ) {
while ( 0 < i ) { //在抵达堆顶之前,反复地
Rank j = Parent ( i ); //考查[i]之父亲[j]
if ( lt ( A[i], A[j] ) ) break; //一旦父子顺序,上滤旋即完成;否则
swap ( A[i], A[j] ); i = j; //父子换位,并继续考查上一层
} //while
return i; //返回上滤最终抵达的位置
}

元素删除

算法

template <typename T> T PQ_ComplHeap<T>::delMax() { //删除非空完全二叉堆中优先级最高的词条
T maxElem = _elem[0]; _elem[0] = _elem[ --_size ]; //摘除堆顶(首词条),代之以末词条
percolateDown ( _elem, _size, 0 ); //对新堆顶实施下滤
return maxElem; //返回此前备份的最大词条
}

下滤

template <typename T> T PQ_ComplHeap<T>::delMax() { //删除非空完全二叉堆中优先级最高的词条
T maxElem = _elem[0]; _elem[0] = _elem[ --_size ]; //摘除堆顶(首词条),代之以末词条
percolateDown ( _elem, _size, 0 ); //对新堆顶实施下滤
return maxElem; //返回此前备份的最大词条
}

建堆

Floyd算法

template <typename T> void heapify ( T* A, const Rank n ) { //Floyd建堆算法,O(n)时间
for ( int i = n/2 - 1; 0 <= i; i-- ) //自底而上,依次
percolateDown ( A, n, i ); //下滤各内部节点
}

就地排序

template <typename T> void Vector<T>::heapSort ( Rank lo, Rank hi ) { //0 <= lo < hi <= size
T* A = _elem + lo; Rank n = hi - lo; heapify( A, n ); //将待排序区间建成一个完全二叉堆,O(n)
while ( 0 < --n ) //反复地摘除最大元并归入已排序的后缀,直至堆空
{ swap( A[0], A[n] ); percolateDown( A, n, 0 ); } //堆顶与末元素对换,再下滤
}

堆排序扩展题目

已知一个几乎有序的数组,几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离可以不超过k,并且k相对于数组来说比较小。请选择一个合适的 排序算法针对这个数据进行排序。

import java.util.PriorityQueue;
// 小根堆
public void sortedArrDistanceLessK(int[] arr, int k) {
PriorityQueue<Integer> heap = new PriorityQueue<>();
int index = 0;
for (; index <= Math.min(arr.length, k); index++) {
heap.add(arr[index]);
}
int i = 0;
for (; index < arr.length; i++, index++) {
heap.add(arr[index]);
arr[i] = heap.poll();
}
while (!heap.isEmpty()) {
arr[i++] = heap.poll();
}
}

荷兰国旗问题

问题一

给定一个数组arr,和一个数num,请把小于等于num的数放在数组的左边,大于num的数放在数组的右边。要求额外空间复杂度0(1),时间复杂度0(N)

[i]<=num,[i]和<=区的下一个数交换,<=区右扩,i++

[i]>num,i++

问题二(荷兰国旗问题)

给定一个数组arr,和一个数num,请把小于num的数放在数组的左边,等于num的数放 在数组的中间,大于nu m的数放在数组的右边。要求额外空间复杂度O(1),时间复杂度 0(N)

[i]<num,[i]和<=区的下一个数交换,<区右扩,i++

[i]==num,i++

[i]>num, [i]和>区前一个交换,>区左扩

public static int[] partition(int[] arr, int l, int r, int p) {
int less = l - 1;
int more = r + 1;
while (l < more) {
if (arr[l] < p) {
swap(arr, ++less, l++);
} else if (arr[l] > p) {
swap(arr, --more, l);
} else {
l++;
}
}
return new int[] { less + 1, more - 1 };
}

不改进的快速排序

1)把数组范围中的最后一个数作为划分值,然后把数组通过荷兰国旗问题分成三个部分:

​ 左侧<划分值、中间二二划分值、右侧>划分值

2)对左侧范围和右侧范围,递归执行

分析

1)划分值越靠近两侧,复杂度越高;划分值越靠近中间,复杂度越低

2)可以轻而易举的举出最差的例子,所以不改进的快速排序时间复杂度为0(N^2)

随机快速排序(改进的快速排序)

1)在数组范围中,等概率随机选一个数作为划分值,然后把数组通过荷兰国旗问题

​ 分成三个部分:左侧〈划分值、中间二二划分值、右侧〉划分值

2)对左侧范围和右侧范围,递归执行

3)时间复杂度为0(N * logN

import java.util.Arrays;

public class
QuickSort { public static void QuickSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
quickSort(arr, 0, arr.length - 1);
} public 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);
}
} //荷兰国旗问题
public 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 i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}

C++实现快速排序

快速排序算法

template <typename T> //向量快速排序
void Vector<T>::quickSort ( Rank lo, Rank hi ) { //0 <= lo < hi <= size
if ( hi - lo < 2 ) return; //单元素区间自然有序,否则...
Rank mi = partition ( lo, hi ); //在[lo, hi)内构造轴点
quickSort ( lo, mi ); //对前缀递归排序
quickSort ( mi + 1, hi ); //对后缀递归排序
}

快速分化算法

template <typename T> //向量快速排序
void Vector<T>::quickSort ( Rank lo, Rank hi ) { //0 <= lo < hi <= size
if ( hi - lo < 2 ) return; //单元素区间自然有序,否则...
Rank mi = partition ( lo, hi ); //在[lo, hi)内构造轴点
quickSort ( lo, mi ); //对前缀递归排序
quickSort ( mi + 1, hi ); //对后缀递归排序
}

应对退化

template <typename T> //轴点构造算法:通过调整元素位置构造区间[lo, hi)的轴点,并返回其秩
//版本B:可优化处理多个关键码雷同的退化情况
Rank Vector<T>::partition ( Rank lo, Rank hi ) {
swap ( _elem[lo], _elem[ lo + rand() % ( hi - lo ) ] ); //任选一个元素与首元素交换
hi--; T pivot = _elem[lo]; //以首元素为候选轴点——经以上交换,等效于随机选取
while ( lo < hi ) { //从向量的两端交替地向中间扫描
while ( lo < hi )
if ( pivot < _elem[hi] ) //在大于pivot的前提下
hi--; //向左拓展右端子向量
else //直至遇到不大于pivot者
{ _elem[lo++] = _elem[hi]; break; } //将其归入左端子向量
while ( lo < hi )
if ( _elem[lo] < pivot ) //在小于pivot的前提下
lo++; //向右拓展左端子向量
else //直至遇到不小于pivot者
{ _elem[hi--] = _elem[lo]; break; } //将其归入右端子向量
} //assert: lo == hi
_elem[lo] = pivot; //将备份的轴点记录置于前、后子向量之间
return lo; //返回轴点的秩
}

数据结构与算法——认识O(NlogN)的排序(1)的更多相关文章

  1. 数据结构与算法——认识O(NlogN)的排序(2)

    输入整型数组和排序标识,对其元素按照升序或降序进行排序 (一组测试用例可能会有多组数据) 接口说明 原型: void sortIntegerArray(Integer[] pIntegerArray, ...

  2. Java数据结构和算法(九)——高级排序

    春晚好看吗?不存在的!!! 在Java数据结构和算法(三)——冒泡.选择.插入排序算法中我们介绍了三种简单的排序算法,它们的时间复杂度大O表示法都是O(N2),如果数据量少,我们还能忍受,但是数据量大 ...

  3. 为什么我要放弃javaScript数据结构与算法(第十章)—— 排序和搜索算法

    本章将会学习最常见的排序和搜索算法,如冒泡排序.选择排序.插入排序.归并排序.快速排序和堆排序,以及顺序排序和二叉搜索算法. 第十章 排序和搜索算法 排序算法 我们会从一个最慢的开始,接着是一些性能好 ...

  4. python 下的数据结构与算法---6:6大排序算法

    顶先最后推荐:哈哈,意思是放到顶部强调其重要性,但是应该我总结的六种算法看完了后再看的一篇醍醐灌顶的文章 一:冒泡排序(Bubble Sort) 原理:假设有n个数,第一轮时:从第一个元素开始,与相邻 ...

  5. Java数据结构和算法之数组与简单排序

    一.数组于简单排序 数组 数组(array)是相同类型变量的集合,可以使用共同的名字引用它.数组可被定义为任何类型,可以是一维或多维.数组中的一个特别要素是通过下标来访问它.数组提供了一种将有联系的信 ...

  6. Hark的数据结构与算法练习之鸽巢排序

    算法说明 鸽巢排序是分布排序的一种,我理解其实鸽巢就是计数排序的简化版,不同之处就是鸽巢是不稳定的,计数排序是稳定的. 逻辑很简单,就是先找出待排数组的最大值maxNum,然后实例一个maxNum+1 ...

  7. Hark的数据结构与算法练习之地精(侏儒)排序

    算法说明 地精排序是交换排序的一种,它是冒泡排序的一种改良,我感觉和鸡尾酒排序挺像的. 不同之处是鸡尾酒排序是从小到大,然后再从大到小切换着排序的.而地精排序是上来先从小到大排序,碰到交换到再从大到小 ...

  8. Hark的数据结构与算法练习之臭皮匠排序

    算法说明 个人感觉是没有意义的算法,只是用来作为学术研究.或者说开拓一下思维. 从wikipedia copy来的一句解释的话:Stooge排序是一种低效的递归排序算法,甚至慢于冒泡排序.在<算 ...

  9. 《Java数据结构与算法》笔记-CH3简单排序

    class ArrayBub { private long[] arr; private int nElement; public ArrayBub(int size) { arr = new lon ...

随机推荐

  1. (7)opencv图片内部的基本处理

    就是,给定我们一张图片,我们可以对图片的每一个像素的色彩进行处理 比如,我们的原图是这个样子 然后我首先将他变成灰度图(灰度图的行道是1,就是chanaual是1) 然后,我又将灰色图片的黑白进行颠倒 ...

  2. spring boot redis 缓存(cache)集成

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  3. redhat8 不支持ansible批量管理解决方案

    redhat8默认不安装python,因此无法通过python去管理,直接上解决方案. dnf install python3 -y alternatives --set python /usr/bi ...

  4. 使用NtQueryInformationFile函数获得不到完整路径

    #include <windows.h> #include <iostream> using namespace std; typedef struct _OBJECT_NAM ...

  5. 实盘交易哪些代码BUG产生严重亏损

    1.少写一个return,疯狂开平2900次,以爆仓结束 2.在上生产环境前,不小心误删除了一个“!”(我至今也不清楚为什么会误删了,晕),导致平仓逻辑一直不满足,不止损,让我损失惨重! 3.卖单变买 ...

  6. 新iPhone上市会让富士康迎来新一轮的“用工荒”吗?

    新iPhone上市,在接下来的几个月内,中国制造会迎来一段非常忙碌或者说忙乱的日子,之所以说忙碌,是在于苹果的订单量常常大得吓人,而之所以说忙乱,则在于连同富士康.和硕.绿点科技等制造业巨头都可能遭遇 ...

  7. 求1+2+3+…..+n

    [问题]求1+2+3+…+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C). [思路]由于题目好多运算符不能用,我们只有想到使用递 ...

  8. java-正则表达式判断移动联通电信手机号

    package com.linbilin.phone; import java.util.regex.Matcher; import java.util.regex.Pattern; public c ...

  9. EF Core开发模式之Code First

    Code First顾名思义,代码为先.首先编写完相关的实体类及DbContext派生类,然后通过映射关系自动在数据库中完成数据库表的创建. 本例中创建一个班级和学生的管理,主要有班级类MyClass ...

  10. Thread--两线程交替打印

    package t3.copy; public class ThreadA extends Thread { private Object lock; public ThreadA(Object lo ...