算法复杂度

稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。

不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。

时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。

空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。

一:冒泡排序

经典的排序算法,通过依次比较相邻两个元素之间的大小,从头比较到尾,相当于一个水泡从下面一直往上,故而称为冒泡排序。

步骤:1.比较两个相邻元素的大小,如果比它大(小),就将其交换。

2.从下标0开始扫描,一直扫描到尾部,每次比较都将最大(小)的交换至最后。

3.继续比较,重复上述过程。

代码:

void Bubble Sort(int *arr,int len)
{
for(int i=0;i<len-1;++i) //比较的次数
{
for(int j=0;j<len-i-1;++j)
{
if(arr[j]>arr[j+1])
swap(arr[j],arr[j+1]);
}
}
}

二:选择排序

选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

步骤:

1.先进行第一次比较,找出数组最大(小)的元素,将其放在第一位,目前已知第一位是最大(小)的元素。

2.从第二个下标位置开始,找出剩余数组中最大(小)的元素,放在第二位。

3.继续重复寻找,直到将其全部排序

代码:

void Select Sort(int *arr,int len)
{
int temp;
for(int i=0;i<len-1;++i)
{
temp=i;
for(int j=i+1;j<len;++j)
{
if(arr[j]>arr[j+1])
temp=j;
}
swap(arr[i],arr[temp]);
}
}

三:插入排序

插入排序(英语:Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

步骤:

1.首先认为第一个元素是已经排序好的,那么从第二个元素开始,如果比第一个小,那么就将其排在第一位,第一个元素后移。

2.同样,继续从第三个开始,从已经排序好的后面开始比较,如果比第二个小,就与第一个比较,元素依次后移。

3.对后面的元素重复操作,一直到比较完成。

代码:

void Insert Sort(int *arr,int len)
{
int temp;
for(int i=1;i<len;++i)
{
int j=i-1;
temp=arr[i];
while(j>=0 && temp>arr[j])
{
arr[j+1]=arr[j];
--j;
}
arr[j+1]=temp;
}
}

四:希尔排序

      希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:

插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。

但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。

先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。

代码:

void shellsort1(int a[], int n)
{
int i, j, gap; for (gap = n / 2; gap > 0; gap /= 2) //步长
for (i = 0; i < gap; i++) //直接插入排序
{
for (j = i + gap; j < n; j += gap)
if (a[j] < a[j - gap])
{
int temp = a[j];
int k = j - gap;
while (k >= 0 && a[k] > temp)
{
a[k + gap] = a[k];
k -= gap;
}
a[k + gap] = temp;
}
}
}

但这种略显复杂,稍做优化

void shellsort2(int a[], int n)
{
int j, gap; for (gap = n / 2; gap > 0; gap /= 2)
for (j = gap; j < n; j++)//从数组第gap个元素开始
if (a[j] < a[j - gap])//每个元素与自己组内的数据进行直接插入排序
{
int temp = a[j];
int k = j - gap;
while (k >= 0 && a[k] > temp)
{
a[k + gap] = a[k];
k -= gap;
}
a[k + gap] = temp;
}
}

五:归并排序

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。

  • 把长度为n的输入序列分成两个长度为n/2的子序列;
  • 对这两个子序列分别采用归并排序;
  • 将两个排序好的子序列合并成一个最终的排序序列。
//将有二个有序数列a[first...mid]和a[mid...last]合并。
void mergearray(int a[], int first, int mid, int last, int temp[])
{
int i = first, j = mid + 1;
int m = mid, n = last;
int k = 0; while (i <= m && j <= n)
{
if (a[i] <= a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
} while (i <= m)
temp[k++] = a[i++]; while (j <= n)
temp[k++] = a[j++]; for (i = 0; i < k; i++)
a[first + i] = temp[i];
}
void mergesort(int a[], int first, int last, int temp[])
{
if (first < last)
{
int mid = (first + last) / 2;
mergesort(a, first, mid, temp); //左边有序
mergesort(a, mid + 1, last, temp); //右边有序
mergearray(a, first, mid, last, temp); //再将二个有序数列合并
}
} bool MergeSort(int a[], int n)
{
int *p = new int[n];
if (p == NULL)
return false;
mergesort(a, 0, n - 1, p);
delete[] p;
return true;
}

六:快速排序

想必用的最多的就是快排了吧,用sort用得不亦乐乎。好吧,回归正话。

快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。

步骤为:

  1. 从数列中挑出一个元素,称为“基准”(pivot),
  2. 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任何一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。

递归到最底部时,数列的大小是零或一,也就是已经排序好了。这个算法一定会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int Partion(int *arr,int low,int high)
{
int temp=arr[low];
while(low<high)
{
while(low<high && arr[high]>=temp)
--high;
swap(arr[low],arr[high]);
//arr[low]=arr[high];
while(low<high && arr[low]<=temp)
++low;
swap(arr[low],arr[high]);
//arr[high]=arr[low];
}
return low;
} void quicksort(int *arr,int low,int high)
{
if(low<high)
{
int t=Partion(arr,low,high);
quicksort(arr,low,t-1);
quicksort(arr,t+1,high);
}
} int main()
{
int a[5];
for(int i=0;i<5;++i)
scanf("%d",&a[i]);
quicksort(a,0,4);
printf("%d %d %d %d %d",a[0],a[1],a[2],a[3],a[4]);
return 0;
}

待更新……

(PS:本期部分素材来源于https://www.cnblogs.com/onepixel/articles/7674659.html

最新文章

  1. 23种设计模式--单例模式-Singleton
  2. Lucene的评分(score)机制研究
  3. Android ListView 常用技巧
  4. memcached安装配置
  5. Beta--项目冲刺第七天
  6. [转载]MySQL将DateTime时间类型格式化
  7. HttpClient请求发送的几种用法:
  8. Linux 4.6分支已到生命尽头 请尽快升级至Linux 4.7.1
  9. Tiling Up Blocks_DP
  10. 在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke 解决办法
  11. 【转载】MySQL 5.6主从Slave_IO_Running:Connecting/error connecting to master *- retry
  12. 用js实现简单排序算法
  13. Database name和SID
  14. 面试题-Java基础-垃圾回收
  15. Windows进程间通信(下)
  16. npm的使用总结
  17. python实现线性回归
  18. ECMAScript6 入门教程记录 变量的解构赋值
  19. 浅谈2017noip信息奥赛普及组试题
  20. Asp.Net JsonResult重写

热门文章

  1. UNIX环境编程学习——反思认识
  2. Sahara中的数据模型
  3. select readonly 不能看到其它选项解决方式
  4. C++常用字符串分割方法实例汇总
  5. Codeforces--596A--Wilbur and Swimming Pool(数学)
  6. SpringMVC中url映射到Controller
  7. php的string编码类型
  8. django的admin后台管理如何更改为中文
  9. js动态追加的元素如何触发事件
  10. windows phone数据网络开发