史上最全的排序算法讲解--作为程序员的你一定要知道

十大排序算法可以说是每个程序员都必须得掌握的了,花了一天的时间把代码实现且整理了一下,为了方便大家学习,我把它整理成一篇文章,每种算法会有简单的算法思想描述,为了方便大家理解,通过动图给大家演示.

基本概念
有些人可能不知道什么是稳定排序、原地排序、时间复杂度、空间复杂度,我这里先简单解释一下:
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学习资料

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值