十大排序算法可以说是每个程序员都必须得掌握的了,花了一天的时间把代码实现且整理了一下,为了方便大家学习,我把它整理成一篇文章,每种算法会有简单的算法思想描述,为了方便大家理解,通过动图给大家演示.
基本概念
有些人可能不知道什么是稳定排序、原地排序、时间复杂度、空间复杂度,我这里先简单解释一下:
1、稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 仍然在 b 的前面,则为稳定排序。
2、非稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 可能不在 b 的前面,则为非稳定排序。
3、原地排序:原地排序就是指在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序。
4、非原地排序:需要利用额外的数组来辅助排序。
5、时间复杂度:一个算法执行所消耗的时间。
6、空间复杂度:运行完一个算法所需的内存大小。
下图为各个算法性能列表
一、冒泡排序算法
算法性质:1、时间复杂度:O(n2) 2、空间复杂度:O(1) 3、稳定排序 4、原地排序
过程简单描述:
1、把第一个元素与第二个元素比较,如果第一个比第二个大,则交换他们的位置。接着继续比较第二个与第三个元素,如果第二个比第三个大,则交换他们的位置….
2、我们对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样一趟比较交换下来之后,排在最右的元素就会是最大的数。
3、除去最右的元素,我们对剩余的元素做同样的工作,如此重复下去,直到排序完成。
4、为方便理解我还准备了动图:
c代码实现
int* bubbleSort1(int arr[] ,int n)
{
if (arr == NULL || n < 2) { return arr; }
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n - i - 1; j++)
{
if (arr[j + 1] < arr[j])
{
flag = 0;
swap_2_num(arr[j + 1],arr[j]);
}
}
}
return arr;
}
冒泡排序改进版c
int* bubbleSort1(int arr[] ,int n)
{
if (arr == NULL || n < 2) { return arr; }
for (int i = 0; i < n; i++)
{
int flag = 1; //标志位
for (int j = 0; j < n - i - 1; j++)
{
if (arr[j + 1] < arr[j])
{
flag = 0;
swap_2_num(arr[j + 1],arr[j]);
//swap_2_num交换两个数函数
}
}
//一趟下来是否发生位置交换
if (flag) {break;}
}
return arr;
}
python代码实现
def bubble_sort(mylist):
for i in range(0,len(mylist)-1): #n个元素 共有n-1趟
for j in range (i+1,len(mylist)):
if mylist[i]<mylist[j]:
mylist[i],mylist[j] = mylist[j],mylist[i]
return mylist
冒泡排序改进版-python
def bubble_advance(mylist):
for i in range(0,len(mylist)-1): #n个元素 共有n-1趟
flag = True
for j in range (i+1,len(mylist)):
if mylist[i]>mylist[j]:
flag = False
mylist[i],mylist[j] = mylist[j],mylist[i]
if flag:
break
return mylist
二、选择排序
性质:1、时间复杂度:O(n2) 2、空间复杂度:O(1) 3、非稳定排序 4、原地排序
过程简单描述:
1、首先,找到数组中最小的那个元素
2、其次,将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。
3、其次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。
4、如此往复,直到将整个数组排序。这种方法我们称之为选择排序。
为方便理解我还准备了动图:
c代码实现
int* selectSort(int a[],int n)
{
for (int i = 0; i < n - 1; i++)
{
int min = i;
for (int j = i + 1; j < n; j++)
{
if (a[min] > a[j])
{
min = j;
}
}
swap_2_num(a[i],a[min]);
}
return a;
}
python代码实现
def choice(mylist):
for i in range(0,len(mylist)-1): #比较len-1趟.先选第一个为最小值
index = i#选一个最小值 # 记录最小数的索引
for j in range(i+1,len(mylist)): #把最小值与后面的每一个进行比较
if mylist[index] < mylist[j]:
index = j ##改变最小值 i不是最小数时,将 i 和最小数进行交换
if index !=i: ##如果最小值有变 则对调
mylist[index] ,mylist[i] =mylist[i] ,mylist[index]
return mylist
三、插入排序
性质:1、时间复杂度:O(n2) 2、空间复杂度:O(1) 3、稳定排序 4、原地排序
我们在玩打牌的时候,你是怎么整理那些牌的呢?一种简单的方法就是一张一张的来,将每一张牌插入到其他已经有序的牌中的适当位置。当我们给无序数组做排序的时候,为了要插入元素,我们需要腾出空间,将其余所有元素在插入之前都向右移动一位,这种算法我们称之为插入排序。
过程简单描述:
1、从数组第2个元素开始抽取元素。
2、把它与左边第一个元素比较,如果左边第一个元素比它大,则继续与左边第二个元素比较下去,直到遇到不比它大的元素,然后插到这个元素的右边。
3、继续选取第3,4,….n个元素,重复步骤 2 ,选择适当的位置插入。
为方便理解我还准备了动图:
插入排序静态图
c代码实现
int * insertsort(int arr[],int len)
{
if (arr == NULL || len < 2) { return arr; }
for (int i =1;i<len;i++)
{
int index = i;
while (index>0 && arr[index]<arr[index-1])
{
swap_2_num(arr[index],arr[index-1]);
index -=1;
}
}
return arr;
}
python代码实现
def insert_sort(arr):
for i in range(1,len(arr)):
index = i
while index>0 and arr[index-1] > arr[index]:
(arr[index],arr[index-1]) = (arr[index-1],arr[index])
index =index-1
return arr
**四、希尔排序
性质:1、时间复杂度:O(nlogn) 2、空间复杂度:O(1) 3、非稳定排序 4、原地排序
希尔排序可以说是插入排序的一种变种。无论是插入排序还是冒泡排序,如果数组的最大值刚好是在第一位,要将它挪到正确的位置就需要 n - 1 次移动。也就是说,原数组的一个元素如果距离它正确的位置很远的话,则需要与相邻元素交换很多次才能到达正确的位置,这样是相对比较花时间了。
希尔排序就是为了加快速度简单地改进了插入排序,交换不相邻的元素以对数组的局部进行排序。
希尔排序的思想是采用插入排序的方法,先让数组中任意间隔为 h 的元素有序,刚开始 h 的大小可以是 h = n / 2,接着让 h = n / 4,让 h 一直缩小,当 h = 1 时,也就是此时数组中任意间隔为1的元素有序,此时的数组就是有序的了。
为方便理解我还准备了图片:
图1
经过4次排序后,可以看到数据的位置离正确的位置相差不远,此时在通过插入排序就能够快速的对整个数据项排列了。
图2
c代码实现
void print(int array[], int n)
{
for (int i = 0; i < n; i++)
cout << array[i] << " ";
cout << endl;
}
/*
需要注意的是,对各个分组进行插入的时候并不是先对一个组排序完了,
再来对另一个组排序,而是轮流对每个组进行排序。
*/
int shellSort(int array[], int n)
{
//定义变量,记录交换次数
int count = 0;
//定义中间变量,做为临时交换变量
int temp;
//遍历数组(进行排序)
cout << "开始对数组进行排序了..." << endl;
//定义初始增量值 step表示步长
int gap = n;
int step= 2;
do
{
//初始增量变化规律
gap = gap / step;
//gap为分割后子数组的长度,如果step为2,则步长以二倍速度减小 直到减小为0
for (int i = gap; i < n; i++)
{
//遍历每一个子数组
for (int j = i; j >= gap; j-=gap)
{
//每个子数组之间比较
if (array[j] < array[j - gap])
{
temp = array[j]; //交换
array[j] = array[j - gap];
array[j - gap] = temp;
cout << array[j] << "和" << array[j - gap] << "互换了" << endl;
//输出此时数组的顺序
cout << "数组此时的顺序是:";
print(array, 10);
//每交换一次,记录数加1
count++;
}
else//如果大小满足条件 跳出执行下一次循环
{
break;
}
}
}
}
while (gap>1);//仅当gap大于1时满足条件 否则结束算法
cout << "数组排序结束了..." << endl;
return count;
}
python代码实现
后续进一步补充…
关注微信公众号【编程让生活更美好】回复【资料】获取更多 c/c++ python学习资料