1.插入排序:
时间复杂度 : O(n^2)
空间复杂度:O(1)
基本思想:把待排序的纪录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的纪录插入完为止,得到一个新的有序序列.
插入排序的算法思路:
(1)将待插入纪录的值赋值给temp;
(2) 设置开始查找的位置j;
(3) 在数组中进行搜索,搜索中将第j个纪录后移,直至temp>r[j]为止;
(4) 将temp插入r[j+1]的位置上。
void InsertSort(int r[],int length){
int i,j,temp;
for(i = 1; i < length; i++){
temp = r[i];//记录待插入元素
for(j=i-1; r[j]>temp && j>=0; j--){//若待插入元素小于当前比较元素,则当前比较元素后移
r[j+1] = r[j];
}
r[j+1] = temp;
}
}
2.折半插入:
时间复杂度: O(n logn)
空间复杂度: O(1)
基本思想:折半插入不同于直接插入在于比较元素时,直接插入是与之前相邻的元素进行比较,而折半插入则是通过0~i-1的中间元素进行比较,每次比较都能缩小一半,故效率较高。
折半插入的算法思路:
(1)计算 0 ~ i-1 的中间点,用 i 索引处的元素与中间值进行比较,如果 i 索引处的元素大,说明要插入的这个元素应该在中间值和刚加入i索引之间,反之,就是在刚开始的位置 到中间值的位置,这样很简单的完成了折半;
(2)在相应的半个范围里面找插入的位置时,不断的用(1)步骤缩小范围,不停的折半,范围依次缩小为 1/2 1/4 1/8 …….快速的确定出第 i 个元素要插在什么地方;
(3)确定位置之后,将整个序列后移,并将元素插入到相应位置。
void InsertSort(int r[],int length){
int i,j,temp,pos;
for(i=1;i<length;i++){
temp = r[i];
pos = binarySearch(r, i-1 , temp);//通过折半查找出要插入的位置
for(j = i;j>=pos;j--){//元素后移
r[j] = r[j-1];
}
r[pos] = temp;//插入待插入元素
}
}
int binarySearch(int r[],int length,int key){
int low,high,mid;
low = 0;
high = length;
while(low <= high){
mid = (low+high)/2;
if(key > r[mid]){
low = mid+1;
}
else if(key < r[mid]){
high = mid-1;
}
}
return low;
}
3.冒泡排序:
时间复杂度: O(n^2)
空间复杂度:O(1)
冒泡排序的基本思路:每次相邻的两个元素进行相互比较,较大的元素上移,通过每一轮的比较找出未排序元素中的最大元素。
void BubbleSort(int r[], int length){
int i,j,temp;
for(i = 0; i < length-1; i++){
for(j = 0; j < length - i;j++){
if(r[j]>r[j+1])
{
temp = r[j];
r[j] = r[j+1];
r[j+1] = temp;
}
}
}
}
4.选择排序:
时间复杂度: O(n^2)
空间复杂度: O(1)
选择排序的基本思路:
1)第i轮,查找i~length-1数组中的最小值,与数组中第i+1个元素进行交换,直到i==length-1
void SelectionSort(int arr[],int length){
int i,j,temp;
for(i = 0; i < length-1; i++){
for(j = i; j < length; j++){
if(arr[i] > arr[j]){
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
5.归并排序
时间复杂度: O(n logn)
空间复杂度: O(n)
归并排序的基本思路:
比较l[i]和r[j]的大小,若l[i]≤r[j],则将第一个有序表中的元素l[i]复制到arr[k]中,并令i和k分别加上1;否则将第二个有序表中的元素r[j]复制到arr[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,e]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,e]。
void MergeSort(int arr[],int start,int end){
int mid = (start+end)/2;
if(start<end){
MergeSort(arr,start,mid);//把数组分为两个部分
MergeSort(arr,mid+1,end);
Merge(arr,start,mid,end);//合并操作
}
}
void Merge(int arr[],int start,int mid,int end){
int Llength = mid - start+1,Rlength = end - mid;//计算左右数组的长度
int *l = (int *)malloc(sizeof(int)*Llength);//给左右数组分配空间
if(!l)exit(0);
int *r = (int *)malloc(sizeof(int)*Rlength);
if(!r)exit(0);
int i,j,k=start;
for(i=0;i<Llength;i++)//左数组赋值操作
*(l+i) = arr[k++];
for(j=0;j<Rlength;j++,i++)//右数组赋值操作
*(r+j) = arr[k++];
i=0;
j=0;
k=start;
while(i<Llength&&j<Rlength){//二路归并
if(*(r+j) <= *(l+i)){
arr[k++] = *(r+j++);
}
else
{
arr[k++] = *(l+i++);
}
}
if(i<Llength){//插入剩下的元素
for(; i<Llength; i++)
{
arr[k++] = *(l+i);
}
}
if(j<Rlength){
for(; j<Rlength; j++)
{
arr[k++] = *(r+j);
}
}
free(l);//释放使用完的l,r数组
free(r);
}
6.快速排序:
时间复杂度 : O(n logn)
空间复杂度 : O(1)
快速排序的算法思路:
1)设置两个变量i、j,排序开始的时候:low=start,high=end;
2)以第一个数组元素作为关键数据,赋值给key,即key = arr[0];
3)从high开始向前搜索,即由后开始向前搜索(high–),找到第一个小于key的值arr[high],将arr[high]和arr[low]互换;
4)从i开始向后搜索,即由前开始向后搜索(low++),找到第一个大于key的arr[low],将arr[low]和A[high]互换;
5)重复第3、4步,直到low==high,把key值赋给arr[low],一次划分完成。
6)递归继续进行划分,重复1~5过程,直到start == end。
void QuickSort(int arr[],int start,int end){
int low = start, high = end;
int key = arr[low];
while(low < high){
while(low<high && arr[high]>key){
high--;
}
arr[low] = arr[high];
while(low<high && arr[low]<key){
low++;
}
arr[high] = arr[low];
}
arr[low] = key;
if(start < end){
QuickSort(arr,start,low);
QuickSort(arr,low+1,end);
}
}