📜  Python的插入排序

📅  最后修改于: 2020-10-29 01:10:30             🧑  作者: Mango

Python的插入排序

与以前的气泡排序算法相比,插入排序是一种直接且高效的算法。插入排序算法的概念基于纸牌的甲板,在这里我们根据特定的纸牌对扑克牌进行排序。它具有许多优点,但是在数据结构中有许多有效的算法可用。

在玩纸牌时,我们将纸牌的手彼此进行比较。大多数玩家喜欢按升序对卡进行排序,以便他们快速查看自己可以使用的组合。

插入排序的实现既简单又容易,因为通常在开始的编程课程中就进行了介绍。它是一种就地且稳定的算法,对于几乎排序或更少的元素更有利。

插入排序算法不是那么快,因为它使用嵌套循环对元素进行排序。

让我们了解以下术语。

就地和稳定的含义是什么?

  • 就地:就地算法需要更多空间,而无需关心集合的输入大小。执行排序后,它将重写集合中元素的原始存储位置。
  • 稳定:稳定是一个术语,用于管理初始数组中相等对象的相对顺序。

更重要的是,插入排序不需要事先知道数组大小,它一次只能接收一个元素。

关于插入排序的妙处在于,如果我们插入更多要排序的元素-算法将安排在适当的位置而不执行完整的排序。

对于较小的阵列(小于10个),效率更高。现在,让我们了解插入排序的概念。

插入排序的概念

数组实际上在插入排序中溢出了两个部分-未排序部分和已排序部分。

排序的部分包含数组的第一个元素,其他未排序的子部分包含数组的其余部分。将未排序数组中的第一个元素与已排序数组进行比较,以便我们可以将其放入适当的子数组中。

如果右侧值小于左侧,则着重于通过移动所有元素来插入元素。

它将重复发生,直到将all元素插入正确的位置。

使用下面的插入排序对数组进行排序是插入排序的算法。

  • 将清单分成两部分-排序和未排序。
  • 在给定数组上从arr [1]迭代到arr [n]。
  • 比较当前元素和下一个元素。
  • 如果当前元素小于下一个元素,请与之前的元素进行比较,向上移动到较大的元素一个位置,为交换的元素腾出空间。

让我们了解以下示例。

我们将在以下数组中考虑已排序数组中的第一个元素。

[10,4,25,1,5]

将10添加到已排序的子数组的第一步

[10,4,25,1,5]

现在,我们从未排序的数组中获取第一个元素-4。我们将此值存储在新变量temp中。现在,我们可以看到10> 4,然后将10向右移动,并覆盖了先前存储的4。

[10、10、25、1、5](温度= 4)

这里的4小于排序的子数组中的所有元素,因此我们将其插入第一个索引位置。

[4,10,25,1,5]

我们在排序的子数组中有两个元素。

现在检查数字25。我们将其保存到temp变量中。 25> 10以及25> 4,然后将其放在第三位置,并将其添加到已排序的子数组中。

[4,10,25,1,5]

再次检查数字1。将其保存在临时目录中。 1小于25。它将覆盖25。

[4,10,25,25,5] 10> 1,然后再次覆盖

[4,25,10,25,5]

[25,4,10,25,5] 4> 1现在将temp的值设为1

[1、4、10、25、5]

现在,我们在排序的子数组中有4个元素。 5 <25,然后将25移至右侧,并将temp = 5传递至左侧。

[1、4、10、25、25]放置温度= 5

现在,我们只需放置temp值即可获得排序后的数组。

[1、4、5、10、25]

给定的数组已排序。

实作

插入的实现相对容易。我们将使用Python整数数组实现。让我们了解以下示例-

Python程序

# creating a function for insertion
def insertion_sort(list1):

        # Outer loop to traverse through 1 to len(list1)
        for i in range(1, len(list1)):

            value = list1[i]

            # Move elements of list1[0..i-1], that are
            # greater than value, to one position ahead
            # of their current position
            j = i - 1
            while j >= 0 and value < list1[j]:
                list1[j + 1] = list1[j]
                j -= 1
            list1[j + 1] = value
        return list1
            # Driver code to test above

list1 = [10, 5, 13, 8, 2]
print("The unsorted list is:", list1)

print("The sorted list1 is:", insertion_sort(list1))

输出:

The unsorted list is: [10, 5, 13, 8, 2]
The sorted list1 is: [2, 5, 8, 10, 13]

说明:

在上面的代码中,我们创建了一个名为insert_sort(list1)的函数。在函数内部-

  • 我们定义了for循环,用于将列表从1遍历到len(list1)。
  • 在for循环中,在value中分配一个list1的值。每次循环将迭代新值时,都会将其分配给value变量。
  • 接下来,我们将大于的list1 [0…i-1]的元素移到其当前位置之前的一个位置。
  • 现在,我们使用while来检查j是否大于或等于0,并且该小于列表的第一个元素。
  • 如果两个条件都成立,则将第一个元素移至第0索引,并减小j的值,依此类推。
  • 之后,我们调用该函数并传递列表并打印结果。

排序自定义对象

Python提供了使用自定义对象更改算法的灵活性。我们将创建一个自定义类,然后重新定义实际的比较参数,并尝试保持与上述相同的代码。

我们将需要重载运算符,以便以不同的方式对对象进行排序。但是,我们可以通过使用lambda函数传递另一种说法为insertion_sort()函数。 lambda函数在调用排序方法时很方便。

让我们了解以下对自定义对象进行排序的示例。

首先,我们定义Point类:

Python程序

# Creating Point class
class Point:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __str__(self):
        return str.format("({},{})", self.a, self.b)

def insertion_sort(list1, compare_function):
    for i in range(1, len(list1)):
        Value = list1[i]
        Position = i

        while Position > 0 and compare_function(list1[Position - 1], Value):
            list1[Position] = list1[Position - 1]
            Position = Position - 1

        list1[Position] = Value

U = Point(2,3)
V = Point(4,4)
X = Point(3,1)
Y = Point(8,0)
Z = Point(5,2)

list1 = [U,V,X,Y,Z]

# We sort by the x coordinate, ascending
insertion_sort(list1, lambda x, y: x.a > y.a)

for point in list1:
    print(point)

输出:

The points are in the sorted order
(2,3)
(3,1)
(4,4)
(5,2)
(8,0)

使用上面的代码,我们可以对坐标点进行排序。它适用于任何类型的列表。

插入排序中的时间复杂度度

插入排序是一种缓慢的算法;有时,对于大量数据集来说似乎太慢了。但是,它对于小列表或数组很有效。

插入排序的时间复杂度为-O(n2)。它使用两个循环进行迭代。

插入排序的另一个重要优点是:它被称为Shell排序的流行排序算法使用。

插入类型中的辅助空间:O(1)

结论

插入排序是一种简单且效率低下的算法,具有很多优点,但是可以使用更有效的算法。

在本教程中,我们讨论了插入排序的概念及其使用Python编程语言的实现。