常用算法

本文总阅读量
本文最后更新于2 分钟前,文中所描述的信息可能已发生改变。

目录

排序算法

快速排序

选取一个基准(一般是第一个元素),将小于基准的元素放置在基准的左边,大于基准的元素放置在右边,再对左右子序列进行相同的过程直到子序列只有一个元素为止。

c++
void quickSort(int arr[],int low,int high){
    if(low>=high){
        //子序列只有一个元素
        return;
    }
    int pivot = partition(arr,low,high);
    quickSort(arr,low,pivot-1);//基准的左子序列排序
    quickSort(arr,pivot+1,high);//基准的右子序列排序
}
int partition(int arr[],int low,int high){
    int pivot = arr[low];
    while(low<high){
        while(low<high && arr[high]>=pivot) high--;//找到小于基准的元素,low<high为了考虑有序的情况
        arr[low] = arr[high];//进行前置
        while(low<high && arr[low]<=pivot) low++;//找到大于基准的元素
        arr[high] = arr[low];//进行后置
    }
    arr[low] = pivot;//基准位置
    return low;//返回基准位置
}

归并排序

归并排序是选择中间位置的元素为基准,分别将左右子序列排序再合并左右子序列。

c++
void mergeSort(int arr[]){//主函数
    int temp[] = new [arr.length];
    internalSort(arr,temp,0,arr.length-1);
}
void internalSort(int arr[],int temp[],int low,int high){//递归
    if(low<high){
        int middle = (low+high)/2;//基准
        internalSort(arr,temp,low,middle);//对左序列排序
        internalSort(arr,temp,middle+1,high);//对右序列排序
        mergeSortArray(arr,temp,low,middle,high);//合并左右有序序列
    }
}
void mergeSortArray(int arr[],int temp[],int low,int middle,int high){
    int left1 = low;
    int left2 = middle+1;
    int k = 0;
    while(left1<=middle && left2<=high){
        temp[k++] = arr[left1]<arr[left2]?arr[left1++]:arr[left2++];//将较小的那个放入到临时数组中
    }
    while(left1<=middle){//左子序列有剩余
        temp[k++] = arr[left1++];
    }
    while(left2<=high){//右子序列有剩余
        temp[k++] = arr[left2++];
    }
    for(int i=0;i<k;i++){//合并递归中的左右子序列到原数组中
        arr[low+i] = temp[i];//此处的low为待排序的子序列起始位置
    }
}

堆排序

堆是一棵完全二叉树(除了最后一层其他层的元素都是满的)所以可以用数组存储,父节点与子节点之间的关系为:父节点i的左子节点为 2*i+1,右子节点为 2*i+2,子节点i的父节点为(i-1)/2取商。用大根堆得到的是升序的,小根堆得到的是降序的。

c++
#include <iostream>
using namespace std;

class Heap{
    public:
        int arr[];
        Heap(int arr[]):arr(arr){}
        //交换大根堆的堆顶与最后一个元素,再调整堆为大根堆
        void sort(){
            int last = arr.length-1;
            //初始化大根堆
            for(int i=getParentIndex(last);i>=0;--i){
                adjustHeap(i,last);
            }
            //交换并调整堆
            while(last>=0){
                swap(0,last--);
                //这里是从上到下了,除了根元素其他元素都满足大根堆性质,此操作为下滤
                adjustHeap(0,last);
            }
        }
    private:
        int getLeftChildIndex(int parent){
            return 2*i+1;
        }
        int getRightChildIndex(int parent){
            return 2*i+2;
        }
        int getParentIndex(int child){
            return (i-1)/2;
        }
        int swap(int i,int j){
            int k = arr[i];
            arr[i] = arr[j];
            arr[j] = k;
        }
        //自下而上构建堆
        void adjustHeap(int parent,int last){
            int left,right,j;
            left = getLeftChildIndex(parent);
            while(left<=last){
                right = left+1;
                j = arr[left]>arr[right]?left:right;//取子节点中最大的
                if(arr[j]>arr[parent]){//与父节点比较
                    swap(j,parent);//大的上移,子节点不满足大根堆性质,即上滤
                    parent = j;//还要继续看交换后其是否大于左右子节点
                    left = getLeftChildIndex(parent);
                }else{
                    //子节点都小于父节点则不需要调整,到此为止
                    break;
                }
            }
        } 
};
template <typename T>
void printArray(T arr[]){
    //输出数组
    for(i=0,i<arr.length;++i){
        sout<< arr[i] <<" ";
    }
}
int main(){
    int arr[] = {3,5,6,7,1,9,3,2};
    Heap h(arr);
    h.sort();
    printArray(arr);
}

树的遍历

  • 广度优先遍历: 利用队列(出队列表示该节点已经被遍历)。初始化根节点入队列,出一个队列头元素->该元素的左子节点入队列(如果有的话)->右子节点入队列(如果有的话)->队列不为空则继续。是一层一层的遍历。
  • 深度优先遍历:利用栈
    • 前序遍历(先根遍历):遍历次序为根->左->右
    • 中序遍历:遍历次序为左->根->右 遍历结果是二叉排序树元素的有序排列
    • 后序遍历:遍历次序为左->右->根
SpringCloud Eureka篇
设计模式
Valaxy v0.18.5 驱动 | 主题 - Yun v0.18.5
本站总访问量
本站访客数 人次
本站已运行0 天0 小时0 分0 秒后缀