既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
public class ShellSort {
public static void sort(int[] a){
//1.根据a的长度确定增长量h
int h = 1;
while (h < a.length/2){
h = 2*h+1;
}
//2.希尔排序
while ( h>=1 ){
//排序:找到待插入的元素,
for (int i = h; i < a.length; i++) {
for (int j = i; j >= h ; j-=h) {
if (a[j-h]>a[j]){
//交换元素
swap(a,j-h,j);
}else {//j-h 比 j 小,不用交换。
break;
}
}
}
h=h/2;
}
}
private static void swap(int[] a, int i, int j){
int emp;
emp = a[i];
a[i] = a[j];
a[j] = emp;
}
}
2.3 稳定性:不稳定
3. 选择排序
3.1 直接选择排序-原理
【算法思想】
第一趟简单选择排序时,从第一个记录开始,通过 n-1 次关键字的比较,从 n 个记录中选出关键字最小的记录,并和第一个记录进行交换。
第二趟简单选择排序时,从第二个记录开始,通过 n-2 次关键字的比较,从 n-1 个记录中选出关键字最小的记录,并和第二个记录进行交换。
第 i 趟简单选择排序时,从第 i 个记录开始,通过 n-i 次关键字的比较,从 n-i+1 个记录中选出关键字最小的记录,并和第i个记录进行交换。
如此反复,经过 n-1 趟简单选择排序,将把 n-1 个记录排到位,剩下一个最小记录直接在最后,所以共需进行 n-1 趟简单选择排序。
3.2 实现
public class SelectSort {
public static void sort(int[] array){
for (int i = 0; i < array.length-1; i++) {
int k = i;
for (int j = i+1; j < array.length; j++) {
if (array[j] < array[k]){
k = j;
}
}
swap(array,k,i);
}
}
private static void swap(int[] a, int i, int j){
int emp;
emp = a[i];
a[i] = a[j];
a[j] = emp;
}
}
3.3稳定性:不稳定
3.4 双向选择排序(了解)
每一次从无序区间选出最小 + 最大的元素,存放在无序区间的最前和最后,直到全部待排序的数据元素排完 。
public static void selectSort(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
// 无序区间: [0, array.length - i)
// 有序区间: [array.length - i, array.length)
int max = 0;
for (int j = 1; j < array.length - i; j++) {
if (array[j] > array[max]) {
max = j;
}
}
int t = array[max];
array[max] = array[array.length - i - 1];
array[array.length - i - 1] = t;
}
}
4. 堆排序
4.1 原理基本原理也是选择排序,只是不在使用遍历的方式查找无序区间的最大的数,而是通过堆来选择无序区间的最大的数。
【算法思想】
①将待排序记录按照堆的定义建初堆(算法 9.9),并输出堆顶元素。
②调整剩余的记录序列,利用筛选法将前 n-i 个元素重新筛选建成为一个新堆,再输出堆顶元素。
③重复执行步骤②,进行 n-1 次筛选,新筛选成的堆会越来越小,而新堆后面的有序关键
字会越来越多,最后使待排序记录序列成为一个有序的序列,这个过程称之为堆排序。
画图过程比较繁琐,大家可以按照思路以及代码自己画着理解一下。
4.2 实现
public class HeapSort {
public static void sort(int[] array){
//建初堆:升序建大堆,降序建小堆。
for (int i = (array.length-2)/2; i >=0 ; i--) {
shiftDown(array,array.length,i);
}
//维护堆:堆顶元素与最后一个元素交换后,堆顶的“堆性质”被破环,需要维护。此时维护的堆大小应该是依次减小的。
for (int i = 0; i < array.length-1; i++) {
swap(array,0,array.length-i-1);
shiftDown(array,array.length-i-1,0);
}
}
private static void shiftDown(int[] array, int length, int index) {
while (index*2+1 < length){
int left = index*2+1;
int right = left+1;
int max = left;
if (right < length && array[left] < array[right]){
max = right;
}
if (array[index] >= array[max]){
return;
}
swap(array,index,max);
index = max;
}
}
private static void swap(int[] a, int i, int j){
int emp;
emp = a[i];
a[i] = a[j];
a[j] = emp;
}
}
4.3 稳定性:不稳定
5. 冒泡排序
5.1 原理:在无序区间,通过相邻数的比较,将最大的数冒泡到无序区间的最后,持续这个过程,直到数组整体有序
5.2 实现:
public class BubbleSort{
public void sort(long[] array) {
for (int i = 0; i < array.length - 1; i++) {
boolean sorted = true;
for (int j = 0; j < array.length - i - 1; j++) {
if (array[j] > array[j + 1]) {
SortUtil.swap(array, j, j + 1);
sorted = false;
}
}
if (sorted) {
return;
}
}
}
}
5.3 稳定性:稳定
6. 快速排序(重要)
6.1 原理-总览
1. 从待排序区间选择一个数,作为基准值(pivot);
2. Partition: 遍历整个待排序区间,将比基准值小的(可以包含相等的)放到基准值的左边,将比基准值大的(可以包含相等的)放到基准值的
右边;
3. 采用分治思想,对左右两个小区间按照同样的方式处理,直到小区间的长度 == 1,代表已经有序,或者小区间的长度 == 0,代表没有数据。
6.2 原理-partition:快速排序的精髓所在就是 partition 操作,实现这一操作有很多方法,总的一点就是根据 pivot 来分割数据。
6.3 稳定性:不稳定
6.4 原理-基准值的选择
1. 选择边上(左或者右)
2. 随机选择
3. 几数取中(例如三数取中):array[left], array[mid], array[right] 大小是中间的为基准值
6.5 代码实现:
public class QuickSort {
public static void sort(int[] array) {
quickSortRange(array,0,array.length-1);
}
// 为了代码书写方便,我们选择使用左闭右闭的区间表示形式
// from,to 下标的元素都算在区间的元素中
// 左闭右闭的情况下,区间内的元素个数 = to - from + 1;
private static void quickSortRange(int[] array, int from, int to) {
if (to - from +1 <= 1) {
// 区间中元素个数 <= 1 个
return;
}
// 挑选中区间最右边的元素 array[to],
//int pi = partitionMethodA(array, from, to);
//经过该步处理后数组array中的数据呈现: [from,pi)的元素是小于 pivot ;(pi,array.length-1]元素是大于 pivot ;
//pivot == array[pi];
// 按照分治算法的思路,使用相同的方式,处理相同性质的问题,只是问题的规模在变小
int[] index = partitionD(array,from,to);
int left = index[0];
int right = index[1];
quickSortRange(array, from, left); // 针对小于等于 pivot 的区间做处理
quickSortRange(array, right, to); // 针对大于等于 pivot 的区间做处理
}
/**
* 以区间最右边的元素 array[to] 最为 pivot,遍历整个区间,从 from 到 to,移动必要的元素
* 进行分区
* @param array
* @param from
* @param to
* @return 最终 pivot 所在的下标
*/
/*
<= pivot: [from,left];
> pivot : [right,to];
未比较 : (left,right);
*/
private static int partitionA(int[] array, int from, int to) {
int left = from;
int right = to;
int pivot = array[to];
while (left < right){
while (left < right && array[left] <= pivot){
left++;
}
while(left < right && array[right] >= pivot){
right--;
}
swap(array,left,right);
}
swap(array,left,to);
return left;
}
/*
<= pivot: [from,left];
> pivot : [right,to];
未比较 : (left,right);
*/
public static int partitionB(int[] array, int from, int to){
int pivot = array[to];
int left = from;
int right = to;
while(left < right){
while(left < right && array[left] < pivot){
left++;
}
array[right] = array[left];
while(left < right && array[right] > pivot){
right--;
}
array[left] = array[right];
}
array[left] = pivot;
return left;
}
/**
* 对 array 的 [from, to] 区间进行分区
* 分区完成之后,区间被分割为 [<= pivot] pivot [>= pivot]
* 分区过程中,始终保持
* [from, s) 小于 pivot
* [s, i) 大于等于 pivot
* [i, to) 未比较过的元素
* [to, to] pivot
* @param array
* @param from
* @param to
* @return pivot 最终所在下标
*/
public static int partitionC(int[] array,int from,int to){
int s = from;
int pivot = array[to];
for (int i = from; i < to; i++) { // 遍历 [from, to)
// 这里加 == 号也保证不了稳定性,有交换操作
if (array[i] < pivot) {
// TODO: 可以进行简单的优化:如果 i == s,就不交换
swap(array,i,s);
s++;
}
}
array[to] = array[s];
array[s] = pivot;
return s;
}
public static int[] partitionD(int[] array,int from,int to){
int s = from;
int i = from;
int g = to;
int pivot = array[to];
while (g-i+1 > 0){
if (array[i] == pivot){
i++;
}else if (array[i] < pivot){
swap(array,s,i);
s++;i++;
}else {
swap(array,g,i);
g--;
}
}
return new int[] {s-1,i};
}
public static int partitionE(int[]array,int left,int right){
int d = left + 1;
int pivot = array[left];
for (int i = left+1; i <=right ; i++) {
if(array[i] < pivot) {
swap(array,i,d);
d++;
}
}
swap(array,d,left);
return d;
}
private static void swap(int[] a, int i, int j){
![img](https://img-blog.csdnimg.cn/img_convert/c23f3166c3e39c142510663b8c54c433.png)
![img](https://img-blog.csdnimg.cn/img_convert/06469e484b0e2a1fd968d758cc1de79c.png)
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
}
swap(array,d,left);
return d;
}
private static void swap(int[] a, int i, int j){
[外链图片转存中...(img-e5t25YCt-1715707495637)]
[外链图片转存中...(img-QxsJZRjZ-1715707495638)]
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**