1冒泡排序
void bubble_sort(int *arr, int len)
{
bool flag = true;
for (int i = 0; i < len - 1 && flag; ++i)//排序的趟数;最后一个不用再向后比较
{
flag = false;//标志位,看上一轮是否还在交换,若没有进入交换则flag=false说明都已经排好,无需再走一趟,直接跳出循环。
for (int j = 0; j < len - 1 - i; ++j)//每一趟排序找出最大的;排除最后已经排序好的
{
if (arr[j] > arr[j + 1])//相邻交换,将最大的放在最后一个位置
{
flag = true;
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
2.选择排序
void select_sort(int *arr, int len)//从小到大
{
int min = arr[0];
int min_index = 0;
int i = 0;
int j = 0;
for (i = 0; i < len - 1; ++i)
{
min = arr[i];//放最小值
min_index = i;//放最小值的下标
for (j = i + 1; j < len; ++j)//一次循环找出最小数的数值和下标且和arr[i]交换
{
if (min > arr[j])//拿arr[i]与一趟的j比较,找出最小的赋给临时量
{
min = arr[j];
min_index = j;
}
}
if (i != min_index)//最后只做一次交换
{
int tmp = arr[i];
arr[i] = arr[min_index];
arr[min_index] = tmp;
}
}
}
3、插入排序
void insert_sort(int *arr, int len)
{
int j = 0;
int tmp = 0; //
for (int i = 1; i < len; ++i)//第一趟只有一个数,不需要比较
{
tmp = arr[i]; //arr[i]==arr[j+1],也就是将下面的arr[j+1]赋给tmp
for (j = i - 1; j >= 0; --j)//arr[i]从arr[i-1]开始逆向比较
{
if (arr[j] < tmp)//遇到比自己小的为止
{
break;
}
arr[j + 1] = arr[j];//比自己大的值后移
}
arr[j + 1] = tmp;//插入合适位置
}
}
时间复杂度:O(N^2)
空间呢复杂度:O(1)
稳定(不跳跃的比较)
针对于数据量较小,基本有序O(N)
分组多次插入排序-》希尔
4、希尔排序
static void shell(int *arr, int len, int gap)//insert_sort()的变形,insert_sort()一数一组
{
int j = 0;
int tmp = 0;
for (int i = gap; i < len; ++i)//gap个为一组
{
tmp = arr[i];
for (j = i - gap; j >= 0; j-=gap)
{
if (arr[j] < tmp)
{
break;
}
arr[j + gap] = arr[j];
}
arr[j + gap] = tmp;
}
}
void shell_sort(int *arr, int len)
{
shell(arr, len, 3);//多次分组。提高效率,使得数逐渐基本有序
shell(arr, len, 1);
}
void shell_sort(int *arr, int len)
{
int d[]={5,3,1};//宽度
for(int i=0;i<3;i++)
{
shell(arr,len,d[i]);
}
}
分组,岔开分
空间复杂度:O(1)
时间复杂度:O(N^1.3–1.5)
不稳定(跳跃式交换数据)
5、堆排序
首先第一步: 初始化大顶堆(从最后一个有子节点开始往上调整最大堆)
1、建堆的过程是从最后一个子树开始(最下面),然后排序开始,首尾交换
2、每次调整都是从这个要调整的子树的根位置开始
若:父:i
则:左孩子:2*i+1 右孩子:2*i+2
若:左孩子:i 右孩子i+1
则父:(i-1)/2
时间复杂度:o(nlogn)
时间复杂度:o(1)
不稳定
若数据为有序:时间复杂度还是一样的
void adjust(int *arr,int len,int index)
{
int left=index*2+1;
int right=index*2+2;
int max=index;
if(left<len && arr[left]>arr[max])
max=left;
if(right<len && arr[right]>arr[max])
max=right;
if(max ==index)
{
swap(arr[max],arr[index]);
adjust(arr,len,max);
}
}
void head_sort(int* arr,int size)
{
for(int i=size/2-1;i>=0;i++)
{
adjust(arr,size,i);
}
for(int i=size-1;i>=1;i--)
{
swap(arr[0],arr[i]);
adjust(arr,i,0);
}
}
6、快排(不稳定)
递归版:
static int partition(int *arr ,int left, int right)
{
int tmp = arr[left];
while (left < right)//直到left和right重合,此时合适位置找到
{
while (arr[right] > tmp && left < right)
{
right--;
}
arr[left] = arr[right];
while (arr[left] < tmp && left < right)
{
left++;
}
arr[right] = arr[left];
}
arr[left] = tmp;//合适位置赋值
return left;
}
static void quick(int *arr, int left, int right)
{
if (left < right)
{
//将arr[left]放到合适位置,将枢轴返回出来,pivot左侧的都小于arr[left],右侧的都大于
int pivot = partition(arr, left, right);
quick(arr, left, pivot - 1);//枢轴两侧开始递归
quick(arr, pivot + 1, right);
}
}
void quick_sort(int *arr, int len)//递归快速排序
{
quick(arr, 0, len - 1);
}
非递归快排:(重要!)
先操作左边,右边先放里面
栈应该开辟多大呢?sizeof(int)* 2 *(logn+1);
void quick_sort(int *arr,int low,int high)
{
stack<int> st;
int k;
if(low<high)
{
st.push(low);
st,push(high);
while(!st.empty())
{
int i=st.top();
st.pop();
int j=st.top();
st.pop();
k=partition(arr,i,j);
if(i<k-1)
{
st.push(i);
st.push(j);
}
if(k+1<j)
{
st.push(k+1);
st.push(j)
}
}
}
}
时间复杂度:O(nlogn)log以2为底的n
空间复杂度:O(logn)
快排优化:
1,如果前面的有序,那我们就白白把前面的走了一遍———》用随机数随便取一个下标开始
2,三者取中
3,有大量的重复数据——》放一起-》先放两边-》再放周围
4,快有序时,用插入排序
5,使用并行或多线程
7,归并:
void merge(int* arr,int left,int mid,int right) //放到一个新数组中
{
int aux[right-left+1]; //拷贝到新数组中
for(int m=left;m<=right;++m)
{
aux[i]=arr[i];
}
int i=left,j=mid+1;
for(int k=left;i<=mid && j<=right;++k) //归并
{
if(aux[i]<=aux[j]) arr[k]=aux[i++]; //哪边小,把哪边放入数组
else if(aux[i>aux[j]) arr[k]=arr[j++];
else if(i>mid) arr[k]=aux[j++]; //一边完了
else if(j>right) arr[k]=aux[i++];
}
}
void mergesort(int *arr,int left,int right)
{
if(left>=right)
return ;
int mid=(right+left)/2;
mergesort(arr,left,mid);
mergesort(arr,mid+1,right);
merge(arr,left,mid,right);
}
void merge_sort(int* arr,int len)
{
mergesort(int,0,n-1);
}
时间:nlogn
空间:o(n)
时间低,空间高。
8,基数排序:(对找工作来说,了解思想就足够了)
思想:先按照个位数排序,再按照十位数排序,以此类推,这组数中最大数是几位数,就得排几趟。那么每一趟排序又该怎么排呢?举个例子,也就是说如何按照个位数排序呢?
如下图:在排序之前,要开辟十个桶的空间大小,每个通分别放入个位为0,1,2,3,4,5,6,7,8,9的数字,然后再按桶的顺序,将每个桶中的数字拿出来,先拿0号桶中的,全部拿出来之后,再拿一号桶中的,以此类推。这是一趟排序。
再按此规律排十位,百位。最后一次排序,从桶内拿出来就已经是排好的了!
很神奇,这种排序是唯一不需要比较的排序方法!
但这个sort需要的辅助空间却很大:需要十个桶,每个桶都必须开辟这组数个大小。