Python插入排序如何工作?

时间:2012-10-06 00:15:03

标签: python

这是插入排序的Python实现,我试图遵循纸上的值但是一旦计数变量我变得比len(s)大,我不知道该怎么做,它是如何/为什么还在运行?< / p>

def sort_numbers(s):
    for i in range(1, len(s)):
        val = s[i]
        j = i - 1
        while (j >= 0) and (s[j] > val):
            s[j+1] = s[j]
            j = j - 1
        s[j+1] = val

def main():
    x = eval(input("Enter numbers to be sorted: "))
    x = list(x)
    sort_numbers(x)
    print(x)

22 个答案:

答案 0 :(得分:23)

或者,这个:

def ins_sort(k):
    for i in range(1,len(k)):    #since we want to swap an item with previous one, we start from 1
        j = i                    #bcoz reducing i directly will mess our for loop, so we reduce its copy j instead
        temp = k[j]              #temp will be used for comparison with previous items, and sent to the place it belongs
        while j > 0 and temp < k[j-1]: #j>0 bcoz no point going till k[0] since there is no seat available on its left, for temp
            k[j] = k[j-1] #Move the bigger item 1 step right to make room for temp
            j=j-1 #take k[j] all the way left to the place where it has a smaller/no value to its left.
        k[j] = temp
    return k

答案 1 :(得分:10)

考虑[3,2,1]

循环以3开头。因为它是列表中的第一项,所以没有其他事可做。

[3, 2, 1]

下一项是2.它比较2到3,因为2小于3,它交换它们,首先将3放在第二个位置,然后将2放在第一个位置。

[2, 3, 1]

最后一项是1.由于1小于3,因此移动3。

[2, 3, 3]

由于1小于2,因此交换移动2。

[2, 2, 3]

然后它在开头插入1。

[1, 2, 3]

答案 2 :(得分:3)

要了解该实现的工作原理,请在此处查看: http://goo.gl/piDCnm

但是,这是插入排序的一个不太混乱的实现:

def insertion_sort(seq):
    for i in range(1, len(seq)):
        j = i
        while j > 0 and seq[j - 1] > seq[j]:
            seq[j - 1], seq[j] = seq[j], seq[j - 1]
            j -= 1

答案 3 :(得分:3)

递归实现

def insert(x, L):
    if [] == L:      return [x]
    elif x <= L[0]:  return [x] + L
    else:            return [L[0]] + insert(x,L[1:])

def insertion_sort(L):
    if [] == L:  return []
    else:        return insert(L[0], insertion_sort(L[1:]))

# test
import random

L = [random.randint(1,50) for _ in range(10)]

print L
print insertion_sort(L)

答案 4 :(得分:2)

如果我们从左到右考虑一个数组[LeftMost,...,RightMost],插入排序会对每个项目执行以下过程:

  1. 获取当前值i。
  2. 获取值j(其中j = i-1在第一次迭代中,或基本上是i左侧的第一个元素)。在while数组[i]和array [j]的第一次迭代中是连续的元素。例如,如果array = [... 60,100,50,...]和array [i]为50,则array [j]为100。
  3. 如果前一个值大于当前值,则交换这两个值。基本上如果你在这个操作发生之前有[...,60,100,50 ......]这样的东西,你最终会得到[...,60,50,100,...]。我的想法是,只要左侧的元素较低,您就可以移动我留下的每个项目。

      

    这是排序算法的关键。一旦你完成了第i项的处理,就会有一个排序数组,从最初的一直到开始(最左边)。

  4.   
  5. 将j的值减1。并返回步骤1(在此示例中,这将使您比较50和60并交换它们。)
  6.      如果你仔细看一下代码,你永远不会得到i&gt; = len(s)的点(range是一个创建列表的函数,而值i在循环中没有改变) 。您可以将变量i视为一个虚箭头,指向数组中左侧所有已排序元素的位置。变量j只是在i固定的情况下向左移动,以交换原始数组[i]值,直到找到另一个等于或小于它的值。

    旁注(理解算法并不重要,但可能有用):考虑到这一点,您可以推断出该算法的复杂性(在最坏情况下比较中测量)为O(N ^ 2),其中N = len(s )。它类似于有两个嵌套的for语句。

    This video很好地解释了上述内容,你知道他们说了什么,一张图片价值1000字

答案 5 :(得分:2)

有一些信息有助于理解插入排序。

首先,i永远不会超过len(s)。事实上,它也永远不等于它。 range(1, len(s))所做的是产生一个可以迭代的不可变序列。您将在以下声明中使用的内容(让我们假设len(s) = 3):

for i in range(1, len(s)):
    ...

是这样的:

for i in (1, 2):
    ...

您可以自己验证:

>>> list(range(1, 3))
>>> [1, 2]

因此,您将首次使用i = 1进行两次迭代,第二次使用i = 2进行迭代。

其次,它有助于提醒自己,您正在排序的列表实质上包含两部分:已排序的部分(list[0:i-1])和尚未排序的部分({{ 1}})。您在每次迭代时尝试使用插入排序实现的目的是找到一个将当前值放入排序列表的位置。我们很快就会谈到这一点。

第三,算法可以被认为是做两个截然不同的任务。第一个是迭代列表中的所有成员并确保列表已排序。这就是外循环所关注的部分(当然,内循环涉及实际检查,但它有助于实现这种简化)。另一个是为列表中的元素找到合适的位置,以便对列表进行排序。即,如果您有一个列表[list[i:]letters = ['a', 'b', 'd', 'c']显然应该转到'c'letters[2]需要占用'd'以前的地方列表将按升序排序。这是内部'c'循环所做的部分。

实际上,while循环(和while语句)如何确保列表的排序非常聪明。首先,它确保我们不会过度使用(s[j+1] = val条件)。也就是说,我们不选择j >= 0元素,它在Python中是列表中的最后一个元素,以及其他语言,如Java,s[-1]异常。然后,它问:我持有的数字是否低于之前的数字?如果是这样,这意味着列表没有排序,我们需要将更大的第一位移到列表的末尾(如果你愿意的话,向右移动)。注意,我们用来比较其他元素的元素保持不变。我们将其保存在ArrayIndexOutOfBounds变量中。因此,我们不必担心在移动值时通过覆盖它而意外丢失它。

现在,一旦我们向右移动更大的值,我们会递减val并再次提出相同的问题:j的值是否大于s[j]中的值}?我们会继续这样做,直到我们发现价值低于val中的值,或者我们达到val而没有找到更低的价值。这意味着我们持有的是列表中的最小数字。无论哪种方式,我们都会跳出s[0]循环,并使用我们拥有的值覆盖while,这样我们就不会在s[j+1]中失去价值。

要了解它在实践中的外观,请考虑一个列表:val。我们假设我们迭代直到数字[2, 3, 4, 5, 1],此时我们进入while循环,因为1。采取的步骤是:

5 > 1

基本上就是这样。迭代循环,检查当前值之前的值是否低于我们持有的值,如果不是,请将这些值向右移动以为我们的值腾出空间。你有它 - 插入排序。

编辑:code review上有一个非常好的,直观的解释,如果你仍然发现很难看到它是如何运作的。

答案 6 :(得分:1)

def insertionsort(list):
    for i in range(1,len(list)):
        temp=list[i]
        j=i-1
        while temp<+list[j] and j>=0:
            list[j+1]=list[j]
            j=j-1
        list[j+1]=temp
    return list
list=eval(raw_input('Enter a list:'))
print insertionsort(list)

这会对你有帮助。

答案 7 :(得分:0)

def insertion(x):
    for i in range(1, len(x)):
        while x[i - 1] > x[i] and i >= 0:
            x[i - 1], x[i] = x[i], x[i - 1]
            i -= 1
    return x

像这样的东西

答案 8 :(得分:0)

def insertSort(list):
  for i in range(0, len(list)):
    index = list[i] // index holder for swapAt position
    while i > 0 and index < list[i - 1]:
      list[i] = list[i - 1]
      i = i - 1
      list[i] = index
  return list
  

print(insert([3,3,6,1,7,2,8])) -> [1, 2, 3, 3, 6, 7, 8]

答案 9 :(得分:0)

def ins(l):
    for i in range(1, len(l)):
        current_index = i
        current_value = l[i]
        while current_index > 0 and current_value < l[current_index - 1]:
            l[current_index] = l[current_index - 1]
            current_index -= 1
        l[current_index] = current_value
    print(l)

答案 10 :(得分:0)

尝试一下,可以同时使用递增和递减顺序:

import operator

def insertion_sort(arr, reverse=False):
    # check if array is empty or not
    if arr is None:
        raise TypeError("Data cannot be none")

    n = len(arr)
    # if length of array is less than two it is already sorted
    if n < 2:
        return arr

    lgt = operator.gt if reverse else operator.lt

    # Traverse through 1 to len(arr)
    for i in range(1, n):
        key = arr[i]
        j = i-1
        while j >= 0 and lgt(key, arr[j]):
            arr[j+1] = arr[j]
            j -= 1
        arr[j+1] = key
    return arr

li = [1, 4, 8, 9, 42, 0, 36]
print(insertion_sort(li))

答案 11 :(得分:0)

对数组进行排序的简单方法。

# Mutate the constant input 
# loop into the array
# check if the array[j] have to be greater than 0 and a[j] is less than a[j - 1] 
# then swap values and decrease the value swapped.

def insertionSort(array):
  a = array
  for i in range(0,len(a)):
    j = i
    while j > 0 and a[j] < a[j - 1]:
      a[j], a[j - 1] = a[j - 1], a[j]
      j -= 1
  return a

# input-> [2,1,3] then array[j] > 0 and array[j] < array[j - 1] -> swap -> decrease j

答案 12 :(得分:0)

通过递归进行插入排序:

k=1# def insertionsort(a): # should be written before k=1
c=a[:]
def swap(k,c,a):
    if c[k-1] > c[k]:
        c[k-1] = a[k]
        c[k] = a[k-1]
        a = c[:]
        if max(c[:k])!= c[k-1]:
            swap(k-1,c,a)
    if k < len(a)-1:
       return swap(k + 1, c,a)
    return c
return swap(k,c,a)

print(insertionsort(b))

答案 13 :(得分:0)

+有两个for循环和描述性名称的替代方案。

38 => (901,1362,1595,1825,2093,4766)
61 => (17018)
66 => (17011,17015,17014,17013,17012)

答案 14 :(得分:0)

列表切片和冒泡排序的简单组合

s = [54,26,93,17,77,31,44,55,20]

for i in range(1,len(s)+1):
    b = s[0:i]
    a = b
    count = 0

    while count<len(a):                  # while loop to perform the for loop len(a) number of times-like in bubble sort
        for j in range(len(a)-1):        # for loop compares every j'th element with next element
            if a[j] >= a[j+1-len(a)]:
                temp = a[j]
                a[j] = a[j+1-len(a)]
                a[j+1-len(a)] = temp

        count = count+1
print a    

答案 15 :(得分:0)

<?php

$login_email = 'email';
$login_pass = 'pass';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://m.facebook.com/login.php');
curl_setopt($ch, CURLOPT_POSTFIELDS,'charset_test=€,´,€,´,水,Д,Є&email='.urlencode($login_email).'&pass='.urlencode($login_pass).'&login=Login');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept-Charset: utf-8','Accept-Language: en-us,en;q=0.7,bn-bd;q=0.3','Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5')); 
curl_setopt($ch, CURLOPT_COOKIEFILE, getcwd ());
curl_setopt($ch, CURLOPT_COOKIEJAR, getcwd ());
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, "user_agent");
curl_setopt($ch, CURLOPT_REFERER, "http://m.facebook.com");
$fbMain = curl_exec($ch) or die(curl_error($ch));

$url = 'http://m.facebook.com/home.php?refid=18';
curl_setopt($ch, CURLOPT_URL, $url);
$demo_mac=curl_exec($ch);
echo $demo_mac;
?>

你可以在这里看到整个概念 - http://pythonplanet.blogspot.in/2015/07/sorting-algorithm-1-insertion-sort.html

答案 16 :(得分:0)

def insertionSort(alist):
    for index in range(1, len(alist)):

        currentvalue = alist[index]
        position = index

        while position > 0 and alist[position-1] > currentvalue:
            alist[position] = alist[position-1]
            print(alist)
            position -= 1

        alist[position] = currentvalue

alist = [int(i) for i in input().split()]       
insertionSort(alist)

答案 17 :(得分:0)

python range(start, end)函数从start开始计算到end - 1。也就是说,end永远不会成为range()值的一部分。例如,如果您有range(len(A))A是一个10个整数的数组(在Python中,列表),len(A)将为10,range(len(A))将返回(0,1,2,3,4,5,6,7,8,9),以便您可以索引A中的每个元素。

在你的情况下,我永远不会超过len(s) - 1

在纸上编写代码可能很有用,但您必须确保编程语言完全符合您的想法,有时实现并不直观。跟踪程序值的快速而简单的方法是使用print语句。例如:

def sort_numbers(s):
    for i in range(1, len(s)):

        # let's see what values i takes on
        print "i = ", i

        val = s[i]
        j = i - 1
        while (j >= 0) and (s[j] > val):
            s[j+1] = s[j]
            j = j - 1
        s[j+1] = val

答案 18 :(得分:-1)

我查看了一些这些帖子,我认为人们已经过度复杂化了这个问题。如果我做错了,请纠正我,但这是我对此类的解释。

def insert(L): # this creates the definition and assines the list that you input to L
    for i in range(len(L)): # this then loops the next code for the length of the list
        while i > 0 and L[i] < L[i-1]: # this is the main part of the code where it checks
        # if the value from the list is less than the one before it and if it is then it 
        # swaps them around 
            L[i-1], L[i] = L[i], L[i-1] # this code just swaps round the values
            print (L)# prints the list out at the end of each part



L = [5,2,3,7,6,9,7]
insert(L)

使用它输出:

[2, 5, 3, 7, 6, 9, 7]
[2, 3, 5, 7, 6, 9, 7]
[2, 3, 5, 6, 7, 9, 7]
[2, 3, 5, 6, 7, 7, 9]

打印功能也可以从行中删除,并且可以放在for循环之外,以便它只在末尾打印列表。这只会给出最后一行:

[2, 3, 5, 6, 7, 7, 9]

答案 19 :(得分:-1)

def sort_numbers(list):
    for i in range(1, len(list)):
        val = list[i]
        j = i - 1
        while (j >= 0) and (list[j] > val):
            list[j+1] = list[j]
            j = j - 1
        list[j+1] = val

n = int(input("Enter the no. of elements"))
list = []
for i in range(0,n):
  t = int(input())
  list.append(t)

sort_numbers(list)

print list

答案 20 :(得分:-1)

`enter code here`
def insertion_sort(data):
n = len(data)
for i in range(n):
    index = i
    value = data[i]
    while data[index] < data[index-1] and index > 0:
        #print("index : " ,index)
        data[index] = data[index-1]
        data[index-1] = value
        #print(f"DATA[index-1] : { data[index-1] } DATA[index] : { data[index] } " )
        index -= 1
        
    data[index] = value

return data;
    
if __name__ == "__main__":
data = []
size = int(input("How many data you want to enter ? : "))

print("\n-----------------INITIALISING----------------")
for i in range(size):
    temp = int(input(f"Enter element { i + 1 } : "))
    data.append(temp)
    
print("\n-----------------BEFORE SORTING DATA----------")
print(data)

print("\n-----------------AFTER SORTING DATA-----------")
print(insertion_sort(data))

答案 21 :(得分:-5)

    def insertie(x):
    nrc=0
    nrm=0
    for i in range(0,len(x)):
        aux=x[i]
        nrm=nrm+1
        j=i-1
        while j >= 0 and aux < x[j]:
            nrc=nrc+1
            x[j+1]=x[j]
            nrm=nrm+1
            j=j-1
        nrc=nrc+1
        x[j+1]=aux
        nrm=nrm+1
    return x

x=[7,5,4,9,1,4,0,1]
print insertie(x)