目录
概述:
插入排序 ——后一位与前边进行比较
插入排序: 希尔排序 ——将数据划分为几个数据在进行直接排序
比较排序 堆排序 —— 大顶堆排序(自适应建堆,重新自适应排序)
选择排序: 选择排序 ——从数组中选出最小的进行排序,放在左边进行排序
冒泡排序 ——将最大的放在最后,依次循环
交换排序: 快速排序 ——分治法,选一个基准,左子序列放小于基准数,右子序列
放大于基准数
归并排序: 先将数组划分为两个数组,对两个数组进行比较,较小的放在新的数组
中,依次进行
一、插入排序
算法(升序):
1、取第二位与第一位进行比较,若第二位小于第一位,则替换第一位与第二位, 否则不变;
2、依次向后进行移动进行比较替换。
代码:
void InsertSort(int* arr, int a)
{
for(int i =0;i<n;i++)
{
int end =i;
int temp = arr[end+1];
while(end>=0)
{
if(arr[end]>temp)
{
arr[end+1] = arr[end];
end--;
}
else
{
break
}
}
arr[end+1]=temp;
}
}
特性总结:
1、时间复杂度:O(N^2)
二、希尔排序
算法: 1、对数组进行划分,根据gap进行划分,当前数字与gap位之后的数据进行比较,若当前数据大于
gap数之后的数,将其进行调换,如果没有,跳出循环,依次进行;
2、同时gap也在不断发生变化,最后gap==1,进行最后的比较。
void ShellSort(int* arr, int n)
{
int gap =n;
while(gap>1)
{
gap = gap/2;
for(int i =0;i<n-gap;i++)
{
int end =i;
int temp = arr[end+gap];
while(end>=0)
{
if(arr[end]>temp)
{
arr[end+temp]=arr[end];
end -= gap;
}
else
{
break;
}
}
arr[end+gap] = temp;
}
}
}
希尔 排序的特性:
1、插入排序的优化;
2、时间复杂度,因为gap的取值,希尔排序的时间复杂度不固定。
三、堆排序
基本概念:
堆:近似完全二叉树的结构,采用数列储存。
大顶堆:每个节点的值都大于或等于它的左右子节点的值。
小顶堆:每个节点的值都小于或者等于它的左右子节点的值。
性质:
1、用数组arr储存堆结构,对于下标为 i 的节点,他的左子节点为 2x i+1,右子节点为 2 x i+2,其
父节点为( i - 1)/2;
2、最后一个非叶子节点的下标为arr.length / 2;
堆排序基本步骤:
1、将初始堆构建为大顶堆(小顶堆),此堆为初始的无序区;
2、将堆顶元素与最后一个元素交换,得到新的无序区arr[0,1,2,n-1]和有序区arr[n];
3、调整新的无序堆区,因此对当前无序的堆区调整为新堆,后再次将arr[0]与无序区最后一个元
素交换,得到新的无序区arr[0…n-2]和新的有序区arr[n-1,n]。不断重复此过程直到有序区的元素个
数为n-1,则整个排序过程完成。
由一个无序序列建堆:
方法一:向堆中添加元素建堆
void addHeap(vector<int>& arr, int a)
{
arr.push_back(a);
int len = arr.length();
if(len ==1);
return ;
int index = len-1;
for(int i =(len-1)/2;i>=0;i--)
{
if(arr[i]>=a)
break;
if(arr[i]<a)
{
arr[index] = arr[i];
index =i;
}
if(i==0)
brek;
}
arr[index] = a;
}
方法二:自下而上的调整来建堆(eg:大顶堆)
/*
至上而下调整arr[s]的数据,使arr[s,...m]也成为一个大顶堆。
*/
void heapAgjust(vector<int>& arr, int s,int m)
{
int temp =arr[s];//当前的根节点
for(int i =2*s+1;i<=m;i=i*2+1)
{
//左右子树根之间比较
if(i<m&&arr[i]<arr[i+1])//
i++;//i指向较大数据节点的位置
if(temp>=arr[i])
break;
arr[s]=arr[i];
s =i;
}
arr[s] = temp;
}
堆排序
void swap(int a0, int a1)
{
int tmp =a0;
a1 =a0;
a0 = tmp;
}
void HeapSort(vector<int>& arr)
{
//1、处理边界值
int len = arr.size();
if (len<2)
return;
//根据调整创建一个大顶堆
for(int i = (len-1)/2;i>=0;i--)
{
HeapAdjust(arr,i,len-1);
}
//不断缩小无序区
for(int i =len-1;i>=1;i--)
{
//交换第一个与最后一个元素的,使序列arr[0,...len-2]c成为无序区
swap(arr[0],arr[i]);
//将arr[0,...,len-2]重新调整为大顶堆
HeapAdjust(arr,0,i-1);
}
四、 选择排序
算法原理:1、第一次从待排序的数据中选出最小的一个元素,放在起始端,
2、然后选出次小的,放在最小元素的下一个位置,依次类推,直到最后一个元素结
束。
void SelectSort(int* arr,int n)
{
int begin =0;
int end =n-1;
while(begin<end)
{
int maxid = begin;
int minid =end;
for(int i = begin,i<=end;i++)
{
if(arr[i]<arr[minid])
minid =i;
if(arr[i>arr[maxid]])
maxid =i;
}
swap(arr[begin],arr[minid]);
//当最大值在begin时,通过上一步的交换后,最大值的下标为minid
if(begin==maxid)
maxid =minid;
//最大值放在序列结尾
swap(arr[maxid],arr[end]);
begin++;
end--;
}
}
选择排序的算法特点:
1、时间复杂度:O(N^2)
2、空间复杂度:O(1)
3、不稳定,而且效率不高,实际中很少使用
五、冒泡排序
算法原理:(升序)
1、从左到右进行依次比较,若左边大于右边则交换,一直到找到最大的元素,交换到最后;
2、继续从左到右进行比较交换,找到第二最大元素,放在最大元素的前一个位置,依次直到最后。
void BubbleSort(int* arr, int n)
{
for(int i =0;i<n;i++)
{
for(int j =1;j<n-i;j++)
{
if(arr[j-1]>arr[j])
swap(&arr[j-1],&arr[j])
}
}
}
void swap(int* a,int *b)
{
int tmp =*a;
*a = *b;
*b = tmp;
}
冒泡排序的特新总结:
1、时间复杂度:O(N^2)
2、空间复杂度:O(1)
3、不稳定
六、快速排序
分治算法:将问题分解为若干个规模较小、相互独立,且与原问题形式相同的子问题,快速排序是
分治算法的一种。
算法原理:将要排序的数据分割为分独立的两部分,其中一部分的数据比另一部分的数据都小;
然后继续对这两部分数据进行快速排序,整个过程可以递归进行,以此使得所有序列变
为有序序列。
步骤:从数列取出一个元素作为基准元素,以基准元素为标准,将问题分解为两个子序列,左子序
列中所有元素均小于基准值,右 子序列中所有元素均大于基准值,然后最左右子序列重复该过
程,直到所有元素都排列在相应位置上为止。
1、递归版本
//Hoare版本
//left -- 数组的起始位置
//right -- 数组的终点位置(数组长度-1)
int QuickSort(int* arr,int left,int right)
{
if(left>=right)
return;
int begin = left;
int end = right;
int keyi = left
while(left<right)
{
//右边先走,找小
while(left<right&&arr[right]>=arr[keyi])
{
right--;
}
//左边再走,找大
while(left<right && arr[left]<= arr[keyi])
{
left++;
}
Swap(&arr[left], &arr[right]);
}
Swap(&arr[left], &arr[keyi])
keyi =left;
QuickSort(arr,begin,keyi-1);
QuickSort(arr,keyi+1,end);
}
该方法有个特点,当key在最左边,且数组为有序,排序时需要新的栈帧,时间复杂度为n*logn,因此我们可以将key的位置进行随机排放。
七、归并排序
1、递归版
void _MergeSort(int* arr,int* tmp,int left,int right)
{
if(left>=right)
return;
int mid =(right+left)/2;
_MergeSort(arr,tmp,0,mid);
_MergeSort(arr,tmp,mid+1,right);
int left1 =left;
int right1 = mid;
int left2 = mid+1;
int right2 = right;
int k =0;
while(left1<right1&&left2<right2)
{
if(arr[left1]<arr[left2])
{
tmp[k++]=arr[left1++];
}
else
{
tmp[k++]=arr[left2++];
}
}
while(left1<right1)
{
tmp[k++]=arr[left1++];
}
while(left2<right2)
{
tem[k++] = arr[left2++];
}
memcpy(a+left,tmp+left,sizeof(int)*(right-left+1));
}
void megesort(int* arr,int int n)
{
int* tmp = new int[n];
if(tmp==NULL)
{
printf("内存申请失败");
return;
}
_MergeSort(arr,tmp,0,n-1);
delete[] tmp;
}
【数据结构】八大排序算法_x一季花开成海x的博客-CSDN博客