- 再进行第二趟排序,注意 j 的结束下标的位置
public static void bullerSort(int[] array){
boolean flg = true;
for (int i = 0; i < array.length-1; i++) {
for (int j = 0; j < array.length-1-i; j++) {
if(array[j] > array[j+1]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
flg = false;
}
}
if(flg){
break;
}
}
}
五、堆排序
中心思想:建大堆,首“尾”元素交换
- 先将数组变成一个大堆
- 堆顶元素与堆尾的元素互换
- 从堆顶元素向下调整,再次成为大堆,注意调整区间的范围(较上一次-1)
- 堆顶元素和倒数第二个元素互换
- 再次向下调整
- 照此循环,直至堆顶元素
自己实现一个大堆
//向下调整
//这里的end是结束区间的下标,注意不是长度len
public static void adjustDown(int[] array, int begin, int end){
int parent = begin;
int child = parent\*2+1;
while(child <= end){
if(child+1 <= end && array[child+1] > array[child]){
child++;
}
if(array[parent] < array[child]){
int temp = array[parent];
array[parent] = array[child];
array[child] = temp;
}else{
break;
}
parent = child;
child = child\*2+1;
}
}
//建立一个大堆
public static void creayHeap(int[] array){
int parent = (array.length-1-1)/2;
for (int i = parent; i >= 0; i--) {
adjustDown(array,i,array.length-1);
}
}
//堆排序
public static void heapSort(int[] array){
creayHeap(array);
int end = array.length-1;
while(end > 0){
int temp = array[0];
array[0] = array[end];
array[end] = temp;
end--;
adjustDown(array,0,end);
}
}
用Java类建一个堆,好写,不过md这个时间复杂度比较高
//调用一个堆
public static void heapSort(int[] array){
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
for (int i = 0; i < array.length; i++) {
minHeap.offer(array[i]);
}
int i = 0;
while(!minHeap.isEmpty()){
array[i] = minHeap.poll();
i++;
}
}
六、快速排序
中心思想:Partition和分治
- 从待排序区间里选一个数,作为基准值(pivot)
- Partition:遍历整个区间,将比基准值小的放到基准值的左边,将比基准值大的放到基准值的右边
- 分治思想,对左右两个小区间按照同样的方式处理,知道小区间的长度为1,代表已经有序;或小区间的长度为0,代表没有数据
Partition
挖坑法实现Partition
中心思想:右填左坑,左填右坑
- 找一个元素作为基准(pivot)(此处是第一个元素作基准)
- low下标从左边开始遍历,high下标从右边开始遍历,low和high就是“坑”
- 首先low下标作为“坑”,需要比 pivot 小的元素填坑,high–,找到比pivot 小的元素,赋值给low
- 然后high下标作为“坑”,需要比pivot 大的元素填坑,low++,找到比pivot 大的元素,赋值给high
- 当low和high相遇时,此下标指向的元素就是 pivot
- 一次Patition结束,此时low/high的左边是比pivot小的元素,low/high右边是比pivot大的元素
- 返回pivot的下标(low/high),作为下一次Patition的区间
public static int Partition(int[] array, int low, int high){
int pivot = array[low];
while(low < high){
//注意这两个循环的顺序,如果是先low后high,第一个坑没法填,最后一个数白白丧失
//注意可以是 >=和<=,或 >=和<,或 >和<=
//不能是< 和 > , 相等的也交换,死循环
while(low < high && array[high] >= pivot){
high--;
}
array[low] = array[high];
while(low < high && array[low] <= pivot){
low++;
}
array[high] = array[low];
}
array[low] = pivot;
return low;
}
Hoare法实现Partition
中心思想:左右交换
- 找一个元素作为基准(pivot)(此处是第一个元素作基准)
- high从右边开始遍历,left从左边开始遍历
- high找到比 pivot 小的元素,low找到比 pivot 大的元素,交换元素
- high与left相遇时,此下标指向的元素 小于pivot ,与 区间起点 的元素交换
- 返回pivot的下标(low/high),作为下一次Patition的区间
public static void Swap(int[] array, int i, int j){
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
public static int Hoare(int[] array, int low, int high){
int start = low;
int pivot = array[low];
while(low < high){
//注意顺序,先后再前,让high去找low,两者相遇的地方是比temp小的数
//同样可以是>=和<= 或 >和<= 或 >=和<
//如果是>,< 会死循环的
while(low < high && array[high] >= pivot){
high--;
}
while(low < high && array[low] <= pivot){
low++;
}
Swap(array,low,high);
}
Swap(array,low,start);
return low;
}
递归分治
- 通过递归的方式对左右两个小区间再进行快速排序,直到区间长度为1时,递归结束
public static void quickSort(int[] array, int start, int end){
if(start >= end){
return;
}
int pivot = Partition(array,start,end);
quickSort(array,start,pivot-1);
quickSort(array,pivot+1,end);
}
//这一步没JB用,就保持下统一性而已
public static void quickSort(int[] array){
quickSort(array,0,array.length-1);
}
时间空间复杂度
稳定性:不稳定
最坏情况时,可能会出现栈溢出的情况
所以可以通过基准值的选择进行优化
优化
- 基准值的选择
- 选择边上(low或者high)
- 随机选择,可以将随机下标的值与low下标的值互换
- 三数取中,要求 array[mid] <= array[low] <= array[high]
- 待排序区间小于一个阈值时,使用直接插入排序
三数取中
还是array[low] 作基准(pivot)
三数取中
让array[mid] <= array[low] <= array[high]
可以确定其中最大/最小数的位置,在比较其余两个数
//元素交换
public static void Swap(int[] array, int i, int j){
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
//array[mid] <= array[low] <= array[high]
//很多种方法,不一一列举了
public static void ThreeMiddle(int[] array,int low, int high){
int mid = (low+high)/2;
if(array[low] < array[mid]){
Swap(array,low,mid);
}
if(array[high] < array[low]){
Swap(array,low,high);
}
if(array[low] < array[mid]){
Swap(array,low,mid);
}
}
非递归分治
中心思想:区间边界放栈中,怕甚(Partition)一次取两个
- 调用Partition后,找到pivot
- 把当前pivot的左区间和右区间的边界下标放到栈中,当这个区间至少有两个元素的时候,才入栈;若只有一个元素,说明有序了,不再入栈
- 判断栈是否为空,如果不为空的话,弹出栈顶的两个元素,放的顺序决定第一个元素给low还是给high
- 再进行Partition
public static void quickSort2(int[] array){
if(array.length == 0){
return;
}
Stack<Integer> stack = new Stack<>();
stack.push(0);
stack.push(array.length-1);
while(!stack.isEmpty()){
int high = stack.pop();
int low = stack.pop();
int pivot = Partition(array,low,high);
if(pivot > low+1) {
stack.push(low);
stack.push(pivot - 1);
}
if(pivot < high-1) {
stack.push(pivot + 1);
stack.push(high);
}
}
}
七、归并排序
中心思想: 合并两个有序“数组”
先将已有的序列分解成较短的子序列,使每个子序列有序,再将已经有序的子序列合并,得到完全有序的序列,即分解与合并
归并排序(递归)
- 将数组通过递归分解,直到low=high时(即只有一个元素的时候),递归结束
- 利用递归改变left和right,将新的 [ left,mid ] 看作一个数组,将 [ mid+1,right ] 看作一个数组,将两个有序数组 合并成 一个有序数组
public static void merge(int[] array, int low, int mid, int high){
int[] temp = new int[high-low+1];
int k = 0;
int s1 = low;
int e1 = mid;
int s2 = mid+1;
int e2 = high;
while(s1 <= e1 && s2 <= e2){
while(s1 <= e1 && array[s1] <= array[s2]){
temp[k++] = array[s1++];
}
while(s2 <= e2 && array[s2] <= array[s1]){
temp[k++] = array[s2++];
}
}
while(s1 <= e1){
temp[k++] = array[s1++];
}
while(s2 <= e2){
temp[k++] = array[s2++];
}
for (int i = 0; i < temp.length; i++) {
array[i+low] = temp[i];
}
}
public static void mergeSort(int[] array, int low, int high){
if(low == high){
return;
}
int mid = (low+high)/2;
mergeSort(array,low,mid);
mergeSort(array,mid+1,high);
merge(array, low, mid, high);
}
public static void mergeSort(int[] array){
mergeSort(array,0,array.length-1);
}
非递归的归并排序
- 通过gap控制需要合并的两个序列的长度,1–>2–>4–>8
- 在gap的一次循环中,s1、e1、s2、e2遍历所有的序列,合并两个有序的序列
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数同学面临毕业设计项目选题时,很多人都会感到无从下手,尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。
因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!
由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频
如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
自己能力的重要机会。**
因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
[外链图片转存中…(img-6NVIIWSX-1712554566425)]
[外链图片转存中…(img-P0lD45rN-1712554566425)]
[外链图片转存中…(img-PcYMZYnG-1712554566425)]
既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!
由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频
如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
[外链图片转存中…(img-1nmCmN7D-1712554566426)]