Sorting and data structures

Various sorting calculation complexity and spatial complexity comparison

Compare Timsort comparison with other sorting algorithm time complexity (time complexity) of

The complexity of the space (space complexities) Compare

Various sorting algorithms

Hardware under the same conditions, sort the list of the same length, often all the following:

# 打印结果:
'''
quick_sort:0.03600168228149414
sorted:0.003000020980834961
sorted:0.003000020980834961
bubble_sort:11.830676555633545
select_sort:7.196411609649658
insert_sort:6.566375494003296
shell_sort:0.06900382041931152
count_sort:14.809847116470337
merge_sort: 0.06600356101989746
'''

Method 1.python built sorted () and the list.sort () ordering

Built-in data type list method sort (), built-in function sorted ()
the underlying implementation is merge sort, just use the underlying Python can not write implementation, thus avoiding Python itself additional significant overhead, the write speed than our own merge Sort much faster (10 to 20 times), so we have to make use of the sort usually sorted and sort

# Python内置函数sorted()
li = [random.randint(0,100000) for i in range(10000)]
start = time.time()
sorted(li)
print('sorted:%s' % (time.time() - start))

# python内置数据类型list.sort()
li = [random.randint(0,100000) for i in range(10000)]
start = time.time()
li.sort()
print('sorted:%s' % (time.time() - start))

'''
sorted:0.003000020980834961
sorted:0.003000020980834961
'''

2. Bubble Sort

# 冒泡排序
# 最坏的时间复杂度是:(O(n^2)),最优的时间复杂度是:O(n)  有序的列表在内层循环一趟就就return了。
def bubble_sort(l):
    for i in range(len(l)-1):
        # 定一个标志位,做一个排序的优化。如果在循环第一趟的时候,
        # 发现列表是一个有序的列表,就不会走内层循环里面的if条件
        # 判断里面的代码,进行交换数字,flag标志位就不会被置换
        # 成False,进而走内层循环外面的if判断,终止整个函数的运行。

        flag = True
        for j in range(len(l)-i-1):
            if l[j] > l[j+1]:
                l[j],l[j+1] = l[j+1],l[j]
                flag = False
        if flag:
            return
# 冒泡排序
li = [random.randint(0,100000) for i in range(10000)]
start = time.time()
bubble_sort(li)
print('bubble_sort:%s' % (time.time() - start))


'''
bubble_sort:11.830676555633545
'''

3. Select Sort

# 选择排序
def select_sort(l):
    for i in range(len(l)):
        minloc = i
        for j in range(i+1,len(l)):
            if l[j] < l[minloc]:
                l[j],l[minloc] = l[minloc],l[j]

# 选择排序
li = [random.randint(0,100000) for i in range(10000)]
start = time.time()
select_sort(li)
print('select_sort:%s' % (time.time() - start))

'''
select_sort:7.196411609649658
'''

4. insertion sort

# 插入排序
# 时间复杂度 O(n^2)
def insert_sort(l):
    for i in range(1,len(l)):
        j = i-1
        temp = l[i]

        while j >= 0 and l[j] > temp:

            l[j+1] = l[j]
            j = j-1
        l[j+1] = temp

# l=[5,7,4,6,3,1,2,9,8]
# insert_sort(l)
# print(l)


# 插入排序
li = [random.randint(0,100000) for i in range(10000)]
start = time.time()
insert_sort(li)
print('insert_sort:%s' % (time.time() - start))

'''
insert_sort:6.566375494003296
'''

5. Quick Sort

def partition(l,left,right):
    tmp = l[left]
    while left < right:
        while left < right and l[right] >= tmp:
            right = right - 1
        l[left] = l[right]

        while left < right and l[left] <= tmp:
            left =left + 1
        l[right] = l[left]

    l[left] = tmp
    return left

#快速排序
# 时间复杂度:O(nlogn)
def quick_sort(l,left,right):
    if left < right:
        mid = partition(l,left,right)
        quick_sort(l,left,mid-1)
        quick_sort(l,mid+1,right)

# 快排
li = [random.randint(0,100000) for i in range(10000)]
start = time.time()
quick_sort(li, 0, len(li)-1)
print('quick_sort:%s' % (time.time() - start))

'''
quick_sort:0.03600168228149414
'''

6. Shell sort

# 希尔排序
'''
希尔排序是一种分组插入排序算法
首先取一个整数d1=n/2,将元素分为d1个组,魅族相邻元素之间的距离为d1,在各组内进行直接插入排序;
取第二个整数d2=d1/2,重复上述分组排序过程,直到d1=1,即所有元素在同一组内进行直接插入排序。
希尔排序每趟并不使某些元素有序,而是使整体数据越来越接近有序;最后一趟排序使得所有数据有序。
'''

def shell_sort(l):
    gap = len(l) // 2
    while gap > 0:
        for i in range(gap, len(l)):
            tmp = l[i]
            j = i - gap
            while j >= 0 and tmp < l[j]:
                l[j + gap] = l[j]
                j -= gap

            l[j + gap] = tmp
        gap //= 2
# 希尔排序
li = [random.randint(0,100000) for i in range(10000)]
start = time.time()
shell_sort(li)
print('shell_sort:%s' % (time.time() - start))

'''
shell_sort:0.06900382041931152
'''

7. counting sequencing

# 计数排序
def count_sort(l):
    n = len(l)
    res = [None] * n
    # 首次循环遍历, 每个列表的数都统计
    for i in range(n):
        # p 表示 a[i] 大于列表其他数 的次数
        p = 0
        # q 表示 等于 a[i] 的次数
        q = 0
        # 二次循环遍历, 列表中的每个数都和首次循环的数比较
        for j in range(n):
            if l[i] > l[j]:
                p += 1
            elif l[i] == l[j]:
                q += 1
        for k in range(p, p+q):  # q表示 相等的次数,就表示, 从 P 开始索引后, 连续 q 次,都是同样的 数
            res[k] = l[i]
    return res

# 计数排序
li = [random.randint(0,100000) for i in range(10000)]
start = time.time()
count_sort(li)
print('count_sort:%s' % (time.time() - start))

'''
count_sort:14.809847116470337
'''

8. merge sort

Merge sort still use to achieve complete binary tree, it is an efficient sorting algorithm on a merge operation is established, the algorithm is very typical application uses a divide and conquer (Divide and Conquer) is. The merger has been ordered sequences, fully ordered sequence.

Basic process : assume that the initial sequence contains n records, it can be seen as the n ordered subsequences, each subsequence of length 1, then twenty-two merge to give the n / 2 length is 2 or 1 ordered sequence, then twenty-two merge, eventually give up an ordered sequence of length n, which is called two-way merge sort.

The following screenshot from "lying data structure" related chapters realization of easy understanding of the whole code.

The main figure shows two examples of code portions, respectively, split and merge of two parts of the original sequence.

# 归并排序
def merge_sort(lst):
    if len(lst) <= 1:
        return lst          # 从递归中返回长度为1的序列

    middle = len(lst) // 2
    left = merge_sort(lst[:middle])     # 通过不断递归,将原始序列拆分成n个小序列
    right = merge_sort(lst[middle:])
    return merge(left, right)

def merge(left, right):
    i, j = 0, 0
    result = []
    while i < len(left) and j < len(right):  # 比较传入的两个子序列,对两个子序列进行排序
        if left[i] <= right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    result.extend(left[i:])         # 将排好序的子序列合并
    result.extend(right[j:])
    return result

# 归并排序
li = [random.randint(0, 100000) for i in range(10000)]
start = time.time()
lst = merge_sort(li)
print("merge_sort:", time.time() - start)

'''
merge_sort: 0.06600356101989746
'''

Find a list of

Find a list: Find the specified item from the list

Input: a list of elements to be searched

Output: Element index or to find elements

Sequential search:

Starting with the first element of the list, the order of the search until they find.

Binary search:

Ordered list from the candidate region data [0: n] started, by comparing the value of the intermediate value candidate regions lookup treated, the candidate region can be reduced by half.

# 二分查找

data structure

malloc () in the end how to apply the memory space?

malloc()到底从哪里得到了内存空间?

答案是从堆里面获得空间。也就是说函数返回的指针是指向堆里面的一块内存。

      操作系统中有一个记录空闲内存地址的链表。当操作系统收到程序的申请时,就会遍历该链表,然后就寻找第一个空间大于所申请空间的堆结点,然后就将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。

     malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表(Free List)。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块(根据不同的算法而定(将最先找到的不小于申请的大小内存块分配给请求者,将最合适申请大小的空闲内存分配给请求者,或者是分配最大的空闲块内存块)。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。

     调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要进行返回值的判断。

在此也要说明就是因为new和malloc需要符合大众的申请内存空间的要求,针对泛型提供的,分配内存设计到分配算法和查找,此外还要避免内存碎片,所以其效率比较低下,因此有时程序猿会自己重写new和delete,或者创建一个内存池来管理内存,提高程序运行的效率。

Arrays and linked lists

Go to: https://blog.csdn.net/m0_37631322/article/details/81777855

1. What is a linked list

Is a list of references to a storage element of a structure of the next element, the list is connected to the element by element by the pointer;

List is a linear list, the order table contains the so-called linear and linear table lists, order linear table is implemented using an array, arranged in sequential memory, by changing the size of the array. Rather than using the sequential implementation of the list, pointer to realize discontinuous in memory. His point is that the list is a series of discrete memory linked to the kind of reasonable use of memory chips, to solve the problem of space.

Therefore, the nodes on the list to allow insertion and deletion of an arbitrary position on the table, but does not allow random access. There are many lists of different types: one-way linked list, doubly linked list and circular list.

2. singly linked list

Unidirectional chain includes two domains, a domain information, a pointer field. That is way linked list node is divided into two parts, one store or display the information on the node, a second part of the memory address of the next node and the last node points to a null value.

3. doubly linked list

Can be clearly seen from the figure, each node has two links, a node is a point before (when the first link is a link to a null or empty list), the other point after a node (when this last link is a link to a null or empty list). Meaning that a doubly linked list has two pointers, a pointer to a node is a front pointer, the other pointer points to a node.

4. circular list

Circular list is the first node and end nodes are connected together. Before the first circular list node is the last node, and vice versa.

5. The difference between an array and a linked list?

Different: chain is a chain storage structure; storage arrays structural order.

List elements are connected by a pointer to the element array in order, all the elements are sequentially stored.

The list of insertion and deletion of elements array is relatively simple, no moving elements, and relatively easy to implement length expansion, but an element more difficult to find;

Looking for an element of the array is relatively simple, but the insertion and deletion more complicated, since the maximum length of the program need to specify at the outset, so when the maximum length, extended length less convenient list.
The same: two structures can be implemented sequentially stored data, the model was constructed of linear structure.

6. The list of applications, coding practices

Joseph problem:

  传说在公园1世纪的犹太战争中,犹太约瑟夫是公元一世纪著名的历史学家。在罗马人占领乔塔帕特后,39 个犹太人与约瑟夫及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人俘虏,于是决定了一个流传千古的自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报到第3人该人就必须自杀,然后再由下一个人重新报数,直到所有人都自杀身亡为止。然而约瑟夫和他的朋友并不想遵从这个约定,约瑟夫要他的朋友先假装遵从,他将朋友与自己安排在第_个和第_个位置,于是逃过了这场死亡游戏,你知道安排在了第几个嘛?

To solve these problems, use one-way circular list of ways to solve:

//节点类
function Node(elemnt) {
    this.item = elemnt;
    this.next = null;
}
//循环列表需要修改一下构造函数,和遍历时候的判断条件
//构造函数如下;希望从后向前遍历,又不想要建立双向链表,就使用循环链表。
function Llist() {
    this.head = new Node("1");
    this.head.next = this.head;
    this.remove = remove;
    this.insert = insert;
    this.find = find;
    this.display = display;
    //..........
}
function find(number) {
    var curr = this.head;
    while (curr.item != number) {
        curr = curr.next;
    }
    return curr;
}
function insert(element, newElement) {
    var preNode = this.find(element);
    var current = new Node(newElement);
    current.next = preNode.next;
    preNode.next = current;
}
function remove() {
    var current = this.head;
    console.log("remove");		
    //跳过两个,杀死一个
    while(current.next.next != null && current.item!=current.next.next.item){
        var temp = current.next.next;
        current.next.next = temp.next;
        current = temp.next;
        temp.next = null;
    }
    return current;
}
function display(flag,current) {
    var crr = this.head;				
    if(flag){
        while(crr.next.item!="1"){
            console.log(crr.item);
            crr=crr.next;
        }
    }else{   //最后只剩两个直接输出
          console.log(current.item);
          console.log(current.next.item);
         }
}
var Clist = new Llist();
//输入排序
for (var i = 1; i < 41; i++){
    Clist.insert(i.toString(),(i + 1).toString());
}
//先输出所有
Clist.display(1,null);
//通过remove返回最后杀死后的结果其中一个节点
Clist.display(0,Clist.remove());  //16,31

Organizing your code to be learning experience;

7. self-understanding

1) an array of easy to query and modify, but not convenient to add and delete

2) the list for adding and deleting, but not for the query, according to business problems using appropriate data structures and algorithms are at high data volume and high concurrent must be considered

Guess you like

Origin www.cnblogs.com/zhangchaocoming/p/12670550.html