排序算法
顺序/线性查找- O(n)
public class LinearSearch {
public static void main(String[] args){
int[] arr1 = new int[]{34,54,3,2,65,7,34,5,76,34,67};
int target=15;
boolean find_flag = false;
for(int i =0;i< arr1.length;i++){
if (target == arr1[i]){
System.out.printf("Find target %d, the index is %d\n",target,i);
find_flag = true;
break;
}
}//判断是否找到条件在循环外
if (!find_flag){
System.out.println("No existence!");
}
}
}
二分查找 - O(log_2 N) 数组必须有序
class BinarySearch{
public static void main(String[] args) {
int[] arr2 = new int[]{2,4,5,8,12,15,19,26,37,49,51,66,89,100}; //必须是有序数组才行
int target =5;
int head = 0 ;//首索引
int end = arr2.length-1;//尾索引
boolean flag = false;
while (head<=end){
int middle = (head+end) / 2;
if(target == arr2[middle]){
System.out.printf("Find target %d, the index is %d\n",target,middle);
flag = true;
break;
}
if (target > arr2[middle]){
head = middle+1;
}else{
end = middle-1;
}
}
if (!flag){
System.out.println("No existence!");
}
}
}
冒泡排序-O( n 2 n^2 n2)-稳定
public class Bubble {
public static void main(String[] args) {
//相邻的两个元素相比
//第一轮找到一个最大值...第二轮找剩下的最大值...
int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
for (int i =0;i<arr.length;i++){
System.out.print(arr[i]+"\t");
}
System.out.println("\nAfter bubble sort!");
//=========================核心=============================================
for (int i=0;i< arr.length-1;i++){
boolean sorted= true;//优化,刚好有序的机会比较低,所以多了几行代码导致时间更长
for (int j=0;j<arr.length-1-i;j++){ //不用考虑最后的值,因此只需要考虑前len(arr)-1-i个
if(arr[j]>arr[j+1]){
int tmp = arr[j];
arr[j]=arr[j+1];
arr[j+1]=tmp;
sorted = false;
}
}
if(sorted)break;
}
//=========================核心=============================================
for (int i =0;i<arr.length;i++){
System.out.print(arr[i]+"\t");
}
}
}
选择排序-O( n 2 n^2 n2)-不稳定
1.找出最大的元素,然后与最末尾元素进行交换
结果:执行完一轮后,最末尾元素就是最大元素
2.忽略已经找到的元素,重复执行步骤1
public class SelectSOrt {
public static void main(String[] args) {
int[] array = new int[]{56,9,10,19,28,37,34};
for (int i =0;i<array.length;i++){
System.out.print(array[i]+"\t");
}
System.out.println("\nAfter selection sort!");
//=========================核心=============================================
for(int end=array.length-1;end>0;end--){ //最后往前
int maxIndex = 0;//设第一个为最大值
for(int begin = 1; begin <=end; begin++){//从第二个开始比较
if (array[maxIndex] <= array[begin]){
maxIndex = begin;
}
}//结束每一轮轮,交换
int tmp = array[maxIndex];
array[maxIndex] = array[end];//放到最后
array[end]=tmp;
}
//=========================核心=============================================
for (int i =0;i<array.length;i++){
System.out.print(array[i]+"\t");
}
}
}
插入排序-O( n 2 n^2 n2)-稳定
遍历元素,设左边已排好序,从右至左遍历序列,将该元素与左边元素进行比较,若该元素小于左边元素则交换
public class InsertSort {
public static void main(String[] args) {
int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
for (int i=1;i<arr.length;i++){//第0个元素本身有序
int key = arr[i];
int j = i-1;//往前比较
while(j>=0 && arr[j] >key){
arr[j+1] = arr[j];
j--;
}
arr[j+1]=key; //往后移动一位作为新的参考指标
}
for (int i =0;i<arr.length;i++){
System.out.print(arr[i]+"\t");
}
}
}
希尔排序-O(n^1.3)-不稳定
需要使用增量排序(间隔)
然后按照间隔进行插入排序(分组再插入排序)
缩小增量排序
public class ShellSort {
public static void main(String[] args) {
int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
int i,j,inc,key;
// 初始增量:n/2
for (inc= arr.length/2;inc>0;inc/=2){
//插入排序
for (i=inc;i< arr.length;i++){
key =arr[i];
for(j=i;j>=inc && key < arr[j-inc];j-=inc){
arr[j]=arr[j-inc];
}
arr[j]=key;
}
}
for (i =0;i<arr.length;i++){
System.out.print(arr[i]+"\t");
}
}
}
归并排序-O( n l o g n nlogn nlogn)-稳定
首先讲数组进行二分,直到成为单个元素
合并,谁更小放在前面
public class MergeSort {
public static void main(String[] args) {
int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
merge_sort(arr,arr.length);
for (int i =0;i<arr.length;i++){
System.out.print(arr[i]+"\t");
}
}
public static void merge_sort(int[] arr, int n){
int[] tmpArr = new int[arr.length];
if(tmpArr.length!=0){
msort(arr,tmpArr,0,n-1);
}else
{
System.out.println("Fail");
}
}
public static void msort(int[] arr, int[] tmpArr, int left,int right){
//如果只有一个元素,就不需要划分
if (left < right){
//找中间点
int mid = (left+right)/2;
//递归划分左半区
msort(arr,tmpArr,left,mid);
//递归划分右半区
msort(arr,tmpArr,mid+1,right);
//合并
merge(arr,tmpArr,left,mid,right);
}
}
public static void merge(int[] arr, int[] tmpArr, int left,int mid,int right){
//标记左半区第一个未排序的元素
int l_pos = left;
//标记右半区第一个未排序的元素
int r_pos = mid+1;
//临时数组元素下标
int pos = left;
//合并
while (l_pos<=mid && r_pos <=right){
if(arr[l_pos]<arr[r_pos]){//左半区第一个剩余元素更小
tmpArr[pos++]=arr[l_pos++];
}else//右半区第一个元素更小
tmpArr[pos++]=arr[r_pos++];
}
//合并左半区剩余元素
while (l_pos<=mid)
tmpArr[pos++]=arr[l_pos++];
//合并右半区剩余元素
while (r_pos<=right)
tmpArr[pos++]=arr[r_pos++];
//把临时数组中合并后的复制回原来的
while (left<=right){
arr[left]=tmpArr[left];
left++;
}
}
}
快速排序-O( n l o g n nlogn nlogn)-不稳定-分治思想
基准,比基准小的放在它前面,比它大的放在它后面
一般是最后一个数作为基准
第一个数由i(第0个数),j一同指向,i不动,j从第一个数开始扫,j扫到比基数小的停下,对换i,j对应值位置,到达基准位置的时候,交换i和pivot所对应的值;换完后i往下移动一位(第1个数)
//QuickSort
public void QuickSort(int[] arr, int left, int right) {
//出口条件
if (left >= right) {
return;
}
//初始变量
int i = left;
int j = right;
int temp = arr[left];
//移动
while (i < j) {
//从右往左
while (i < j && arr[j] >= temp) {
j--;
}
//放置元素的点
if (i < j) {
arr[i++] = arr[j];
}
//从左往右
while (i < j && arr[i] <= temp) {
i++;
}
//放置元素的点
if (i < j) {
arr[j--] = arr[i];
}
//移动完毕一轮
System.out.println(Arrays.toString(arr));
}
//分治法
arr[i] = temp;
//在i的左边都比temp小 左
QuickSort(arr, left, i - 1);
//在i的右边都比temp大 右
QuickSort(arr, i + 1, right);
}
堆排序-O( n l o g n nlogn nlogn)-不稳定-了解算法
1.对序列进行原地建堆 (第一个数是最大值)
交换堆顶元素与尾元素
堆size-1
对0位置进行1次siftDown操作
直到堆size=1
大顶堆
- 下标为i的节点的父节点下标:(i-1)/2
- 下标为i的节点的左孩子下标:i*2+1
- 下标为i的节点的左孩子下标:i*2+2
二叉树建立