随机打乱数组的方法与算法优化思路

随机打乱数组的方法与算法优化思路

随机打乱数组的方法与算法优化思路

方法1

构造一个空的数组1,把输入数组中的数按顺序随机放入到数组1的空位中。

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import random

def array_rand1(arr):
    print("array rand 1:")
    size = len(arr)
    arr1=[] 
    for i in range(0, size):
        # 初始化空位
        arr1.append(None)
    space_size = len(arr1) # 剩余的空位
    for x in arr:
        # 遍历数组
        # 随机放入空位的序号
        n = random.randint(0, space_size-1)
        # print("放到序号{}的空位".format(n))
        i = 0 # 空位序号
        for y in range(0, size):
            if arr1[y] is None:
                # 数到随机的数字
                if n == i:
                    arr1[y] = x # 放入数字
                    # 空位减1 
                    space_size -= 1
                    print(arr1)
                    break
                # 序号加1
                i += 1
    print("打乱结果:{}".format(arr1))
    return arr1 

输出:

array_rand1:
[None, None, None, None, None, None, None, 1, None, None]
[None, None, None, None, None, None, 2, 1, None, None]
[None, None, None, None, None, None, 2, 1, None, 3]
[4, None, None, None, None, None, 2, 1, None, 3]
[4, None, None, None, 5, None, 2, 1, None, 3]
[4, None, None, None, 5, None, 2, 1, 6, 3]
[4, None, None, 7, 5, None, 2, 1, 6, 3]
[4, 8, None, 7, 5, None, 2, 1, 6, 3]
[4, 8, 9, 7, 5, None, 2, 1, 6, 3]
[4, 8, 9, 7, 5, 10, 2, 1, 6, 3]
打乱结果:[4, 8, 9, 7, 5, 10, 2, 1, 6, 3]

方法2

对方法1进行优化
有序抽取随放入修改为随机抽取有序放入

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import random

def array_rand2(arr):
    print("array rand 2:")
    size = len(arr)
    arr2=arr.copy()
    arr1=[] 
    for x in range(0, size):
        n = random.randint(0, size-1-x)
        arr1.append(arr2[n])
        arr2.pop(n)
        print("{}".format(arr1))
        print("{}".format(arr2))
    print("打乱结果:{}".format(arr1))
    return arr1 

输出:

array_rand2:
[6]
[1, 2, 3, 4, 5, 7, 8, 9, 10]
[6, 9]
[1, 2, 3, 4, 5, 7, 8, 10]
[6, 9, 3]
[1, 2, 4, 5, 7, 8, 10]
[6, 9, 3, 2]
[1, 4, 5, 7, 8, 10]
[6, 9, 3, 2, 1]
[4, 5, 7, 8, 10]
[6, 9, 3, 2, 1, 4]
[5, 7, 8, 10]
[6, 9, 3, 2, 1, 4, 8]
[5, 7, 10]
[6, 9, 3, 2, 1, 4, 8, 5]
[7, 10]
[6, 9, 3, 2, 1, 4, 8, 5, 7]
[10]
[6, 9, 3, 2, 1, 4, 8, 5, 7, 10]
[]
打乱结果:[6, 9, 3, 2, 1, 4, 8, 5, 7, 10]

方法3

对方法2进行优化
方法2中从arr2抽取放入arr1中,arr1和arr2元素总数等于输入的数组。
考虑把乱序后的数组放前面,未乱序的数据放数组后面。可以节约1个arr1的内存。

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import random

def array_rand3(arr):
    print("array_rand3:")
    size = len(arr)
    arr2=arr.copy()
    for x in range(0, size):
        n = random.randint(0, size-1-x)
        t = arr2[n+x]
        arr2.pop(n+x)
        arr2.insert(x, t)
        print("{}".format(arr2))
    print("打乱结果:{}".format(arr2))
    return arr2

输出:

array_rand3:
[10, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[10, 5, 1, 2, 3, 4, 6, 7, 8, 9]
[10, 5, 7, 1, 2, 3, 4, 6, 8, 9]
[10, 5, 7, 1, 2, 3, 4, 6, 8, 9]
[10, 5, 7, 1, 9, 2, 3, 4, 6, 8]
[10, 5, 7, 1, 9, 4, 2, 3, 6, 8]
[10, 5, 7, 1, 9, 4, 6, 2, 3, 8]
[10, 5, 7, 1, 9, 4, 6, 2, 3, 8]
[10, 5, 7, 1, 9, 4, 6, 2, 3, 8]
[10, 5, 7, 1, 9, 4, 6, 2, 3, 8]
打乱结果:[10, 5, 7, 1, 9, 4, 6, 2, 3, 8]

方法4

对方法3进行优化
方法3使用了删除和插入操作比较耗费时间
并且考虑到从未乱序的数组中挑选元素时元素的顺序对挑选结果不造成影响。
任意元素选中概率为(1/(size-x))
因此可以把删除和插入元素修改为调换元素位置

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import random

def array_rand4(arr):
    print("array_rand4:")
    size = len(arr)
    arr2=arr.copy()
    for x in range(0, size):
        n = random.randint(0, size-1-x)
        t = arr2[n+x]
        arr2[n+x]=arr2[x]
        arr2[x]=t
        print("{}".format(arr2))
    print("打乱结果:{}".format(arr2))
    return arr2

输出:

array_rand4:
[4, 2, 3, 1, 5, 6, 7, 8, 9, 10]
[4, 3, 2, 1, 5, 6, 7, 8, 9, 10]
[4, 3, 1, 2, 5, 6, 7, 8, 9, 10]
[4, 3, 1, 9, 5, 6, 7, 8, 2, 10]
[4, 3, 1, 9, 7, 6, 5, 8, 2, 10]
[4, 3, 1, 9, 7, 8, 5, 6, 2, 10]
[4, 3, 1, 9, 7, 8, 5, 6, 2, 10]
[4, 3, 1, 9, 7, 8, 5, 10, 2, 6]
[4, 3, 1, 9, 7, 8, 5, 10, 6, 2]
[4, 3, 1, 9, 7, 8, 5, 10, 6, 2]
打乱结果:[4, 3, 1, 9, 7, 8, 5, 10, 6, 2]

方法5

对方法4进行优化

def array_rand5(arr):
    print("array_rand5:")
    arr2=arr.copy()
    l = len(arr2)
    for i in range(0, l):
        # 从剩下的数中随机选择一个数与arr[i]交换
        # 每个数被选中的概率为1/(l-i)
        n = random.randint(i, l-1)
        # 交换arr[i]和arr[n]
        t = arr2[n]
        arr2[n]=arr2[i]
        arr2[i]=t
        print("{}".format(arr2))
    print("打乱结果:{}".format(arr2))
    return arr2

输出:

array_rand5:
[7, 2, 3, 4, 5, 6, 1, 8, 9, 10]
[7, 1, 3, 4, 5, 6, 2, 8, 9, 10]
[7, 1, 5, 4, 3, 6, 2, 8, 9, 10]
[7, 1, 5, 6, 3, 4, 2, 8, 9, 10]
[7, 1, 5, 6, 10, 4, 2, 8, 9, 3]
[7, 1, 5, 6, 10, 2, 4, 8, 9, 3]
[7, 1, 5, 6, 10, 2, 4, 8, 9, 3]
[7, 1, 5, 6, 10, 2, 4, 3, 9, 8]
[7, 1, 5, 6, 10, 2, 4, 3, 8, 9]
[7, 1, 5, 6, 10, 2, 4, 3, 8, 9]
打乱结果:[7, 1, 5, 6, 10, 2, 4, 3, 8, 9]

完整代码

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import random


# 方法1。
# 构造一个空的数组1。
# 把输入数组中的数按顺序随机放入到数组1的空位中。
def array_rand1(arr):
    print("array_rand1:")
    size = len(arr)
    arr1=[] 
    for i in range(0, size):
        # 初始化空位
        arr1.append(None)
    space_size = len(arr1) # 剩余的空位
    for x in arr:
        # 遍历数组
        # 随机放入空位的序号
        n = random.randint(0, space_size-1)
        # print("放到序号{}的空位".format(n))
        i = 0 # 空位序号
        for y in range(0, size):
            if arr1[y] is None:
                # 数到随机的数字
                if n == i:
                    arr1[y] = x # 放入数字
                    # 空位减1 
                    space_size -= 1
                    print(arr1)
                    break
                # 序号加1
                i += 1
    print("打乱结果:{}".format(arr1))
    return arr1 


# 方法2。
# 对方法1进行优化,有序抽取随放入修改为随机抽取有序放入
def array_rand2(arr):
    print("array_rand2:")
    size = len(arr)
    arr2=arr.copy()
    arr1=[] 
    for x in range(0, size):
        n = random.randint(0, size-1-x)
        arr1.append(arr2[n])
        arr2.pop(n)
        print("{}".format(arr1))
        print("{}".format(arr2))
    print("打乱结果:{}".format(arr1))
    return arr1 


# 方法3。
# 对方法2进行优化
# 方法2中从arr2抽取放入arr1中,arr1和arr2元素总数等于输入的数组。
# 考虑把乱序后的数组放前面,未乱序的数据放数组后面。可以节约1个arr1的内存。
def array_rand3(arr):
    print("array_rand3:")
    size = len(arr)
    arr2=arr.copy()
    for x in range(0, size):
        n = random.randint(0, size-1-x)
        t = arr2[n+x]
        arr2.pop(n+x)
        arr2.insert(x, t)
        print("{}".format(arr2))
    print("打乱结果:{}".format(arr2))
    return arr2

# 方法4。
# 对方法3进行优化
# 方法3使用了删除和插入操作比较耗费时间
# 并且考虑到从未乱序的数组中挑选元素时元素的顺序对挑选结果不造成影响。
# 选中概率为(1/(size-x))
# 因此可以把删除和插入元素修改为调换元素位置
def array_rand4(arr):
    print("array_rand4:")
    size = len(arr)
    arr2=arr.copy()
    for i in range(0, size):
        n = random.randint(0, size-1-i)
        t = arr2[n+i]
        arr2[n+i]=arr2[i]
        arr2[i]=t
        print("{}".format(arr2))
    print("打乱结果:{}".format(arr2))
    return arr2

# 方法5。
# 对方法4进行优化
def array_rand5(arr):
    print("array_rand5:")
    arr2=arr.copy()
    l = len(arr2)
    for i in range(0, l):
        # 从剩下的数中随机选择一个数与arr[i]交换
        # 每个数被选中的概率为1/(l-i)
        n = random.randint(i, l-1)
        # 交换arr[i]和arr[n]
        t = arr2[n]
        arr2[n]=arr2[i]
        arr2[i]=t
        print("{}".format(arr2))
    print("打乱结果:{}".format(arr2))
    return arr2

if __name__ == "__main__":
    '''main'''
    arr = [1,2,3,4,5,6,7,8,9,10]
    array_rand1(arr)
    array_rand2(arr)
    array_rand3(arr)
    array_rand4(arr)
    array_rand5(arr)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值