排序
- 算法-排序(CYC2018)(必看)
- 排序(Interview_Notes)
- 稳定排序与不稳定排序:博客1、博客2
- 荷兰国旗(三色排序):颜色分类
class Solution {
public:
void sortColors(vector<int>& nums) {
int zero=-1,one=0,two=nums.size();
while(one<two){
if(nums[one]==0)
swap(nums[++zero],nums[one++]);
else if(nums[one]==2)
swap(nums[--two],nums[one]);
else
one++;
}
return;
}
};
- 冒泡排序:
void bubblesort(vector<int> &arr){
int len=arr.size();
for(int i=0;i<len-1;i++){
int flag=0;
for(int j=0;j<len-i-1;j++){
if(arr[j]>arr[j+1]){
flag=1;
swap(arr[j],arr[j+1]);
}
}
if(!flag)
break;
}
}
- 选择排序:
void selectsort(vector<int> &arr){
int len=arr.size();
for(int i=0;i<len-1;i++){
int minpos=i;
for(int j=i+1;j<len;j++){
if(arr[j]<arr[minpos])
minpos=j;
}
if(minpos!=i)
swap(arr[minpos],arr[i]);
}
}
- 插入排序:
void insertsort(vector<int> &arr){
int len=arr.size();
for(int i=1;i<len;i++){
int tmp=arr[i],j;
for(j=i-1;j>=0&&tmp<arr[j];j--){
arr[j+1]=arr[j];
}
arr[j+1]=tmp;
}
}
- 希尔排序:插入排序的改进版,间隔的递增序列满足3n+1
void shellsort(vector<int> &arr){
int len=arr.size(),gap=1;
while(gap*3+1<len)
gap=gap*3+1;
while(gap>=1){
for(int i=gap;i<len;i++){
int tmp=arr[i],j;
for(j=i-gap;j>=0&&tmp<arr[j];j-=gap){
arr[j+gap]=arr[j];
}
arr[j+gap]=tmp;
}
gap/=3;
}
}
- 归并排序
void merge(vector<int> &arr,int left,int mid,int right){
int p=left,q=mid+1,i=0;
vector<int> tmp(right-left+1,0);
while(p<=mid&&q<=right){
if(arr[p]<=arr[q])
tmp[i++]=arr[p++];
else
tmp[i++]=arr[q++];
}
while(p<=mid)
tmp[i++]=arr[p++];
while(q<=right)
tmp[i++]=arr[q++];
for(int j=left;j<=right;j++)
arr[j]=tmp[j-left];
}
void mergesort(vector<int> &arr,int left,int right){
if(left>=right)
return;
else{
int mid=(right-left)/2+left;
mergesort(arr,left,mid);
mergesort(arr,mid+1,right);
merge(arr,left,mid,right);
}
}
- 快速排序:
void quicksort(vector<int> &arr,int left,int right){
if(left>=right)
return;
else{
int low=left,high=right,pivot=arr[low];
while(low<high){
while(low<high&&arr[high]>=pivot)
high--;
if(low<high)
arr[low++]=arr[high];//high不要减1了,要将前面的数字摆上来
while(low<high&&arr[low]<pivot)
low++;
if(low<high)
arr[high--]=arr[low];//low不要加1了,后面的数字要摆上来
}
arr[low]=pivot;
quicksort(arr,left,low-1);
quicksort(arr,low+1,right);
}
}
-
堆排序:先构建堆,然后进行n-1次堆顶元素与最后一个元素的交换。
上浮法建堆: 无序数组建立堆最直接的方法是从左到右遍历数组进行上浮操作。 下沉法建堆: 一个更高效的方法是从右至左进行下沉操作,如果一个节点的两个节点都已经是堆有序,那么进行下沉操作可以使得这个节点为根节点的堆有序。 叶子节点不需要进行下沉操作,可以忽略叶子节点的元素,因此只需要遍历一半的元素即可。 交换并下沉: 建好堆之后进行n-1次堆顶元素与最后一个元素的交换,每次交换之后需要从堆顶进行下沉操作维持堆的有序状态。
#include<bits/stdc++.h>
using namespace std;
//大顶堆
class heap{
private:
vector<int> arr;
int len;
public:
heap(vector<int> a):arr(a),len(a.size()-1){}
//上浮
void up(int k){
while(k/2>0){
int p=k/2;
if(arr[p]<arr[k])
swap(arr[p],arr[k]);
k=p;
}
}
//下沉,最重要的函数(必会)
void down(int k){
while(2*k<=len){
int j=2*k;
if(2*k+1<=len&&arr[2*k+1]>arr[j])
j=2*k+1;
if(arr[j]<=arr[k])
break;
swap(arr[k],arr[j]);
k=j;
}
}
void CreateHeap(){
//下沉调整,只用遍历一半
for(int i=len/2;i>=1;i--)
down(i);
//上浮调整
//for(int i=1;i<=len;i++)
// up(i);
}
void HeapSort(){
CreateHeap();
for(int i=1;i<arr.size()-1;i++){
swap(arr[1],arr[len]);
len--;
down(1);
}
}
void print(){
for(int i=1;i<arr.size();i++)
cout<<arr[i]<<" ";
}
};
int main(){
vector<int> arr;
srand(time(NULL));
arr.push_back(-1);
for(int i=0;i<10;i++)
arr.push_back(rand()%100);
heap target(arr);
target.HeapSort();
target.print();
}
并查集
- make-set:把每个结点的父结点置为自身,相当于自己是一个集合
- find:向上找到最终父结点
- union:让一个最终父结点指向另外一个最终父结点实现合并
- 统计有多少个连通分量:计算有多少个结点的parent为自身即可。
优化策略:并查集的两种启发式策略优化
例题:
链表
其它
-
二分查找:搜索旋转排序数组(LeetCode)
二分查找模板:
int l=0; int r=len-1; //是小于等于!不是小于! while(l<=r) { int mid=(r-l)/2+l;//避免相加溢出 if(arr[mid]==target) return mid; if(arr[mid]>target) r=mid-1; else l=mid+1; } return -1;
-
红黑树:红黑树学习笔记
-
最短路径:透彻理解迪杰斯特拉算法
-
最小生成树: 最小生成树的两种方法(Kruskal算法和Prim算法)、数据结构–最小生成树详解
prim:加点法 kruskal:加边法(用并查集判断有无环)
-
哈夫曼树:哈夫曼树及哈夫曼编码
-
哈希:什么叫做哈希冲突?什么是负载因子?如何解决哈希冲突???、平方取中法1、平方取中法2、STL的哈希表底层实现
STL哈希表扩容后要找两倍大后附近的质数。编译器将扩容的空间大小(53、97、193、389…)都自己定义好了,不用重新计算空间。
-
蓄水池采样算法:给出一个数据流,这个数据流的长度很大或者未知。并且对该数据流中数据只能访问一次。现在需要在其中抽取n个数据,且使得所有数据被选中的概率相等,需要用到蓄水池采样算法。
面试宝典
刷题
还是得靠刷题