算法导论—排序算法总结

华电北风吹

天津大学认知计算与应用重点实验室

最后修改日期:2015/8/22


声明:本文涉及的所有排序算法定义功能对输入进行从小到大排序

符号解释:

     n:输入数据个数

Θ(n):n的同阶无穷大


Part I Array Sort

一、选择排序

def SelectSort(a):
    for i in range(0,len(a)-1):
        minIndex=i
        for j in range(i+1,len(a)):
            if a[j]<a[minIndex]:
                minIndex=j
        if minIndex !=i:
            temp=a[minIndex]
            a[minIndex]=a[i]
            a[i]=temp
    return a

a=[2,5,3,8,6,1,4,9]
SelectSort (a)
print(a)
从前往后,依次选择当前位置以后最小的数与当前位置交换

计算复杂度theta(n^2)

二、冒泡排序

def BubbleSort (a):
    k=len(a)
    for i in range(0,k-1):
        for j in range(k-1,i,-1):
            if a[j]<a[j-1]:
                a[j-1],a[j]=a[j],a[j-1]
    return a

a=[2,5,3,8,6,7,1,4,9]
BubbleSort (a)
print(a)

从前往后,反复交换相邻的未按次序排列的元素

计算复杂度theta(n^2)

三、插入排序

def InsertSort(a):
    for j in range(1,len(a)):
        key=a[j]
        i=j-1
        while(i>=0 and a[i]>key):
            a[i+1]=a[i]
            i=i-1
        a[i+1]=key

a=[2,5,3,8,6,1,4,9]
InsertSort (a)
print(a)

从前往后,讲下一个数据插入到前面已经排好序的数组里面

最好的情况:已经从小到大排好序,计算复杂度theta(n)

最坏的情况:输入顺序为从大到小,计算复杂度theta(n^2)

当数据量很大的时候,不必要一个一个往前找,可以根据二分发,减少计算量

 四、归并排序

def MergeSort(a):
    n=len(a)
    if n==1:
        return a
    mid=(n+1)//2
    b=MergeSort(a[0:mid])
    c=MergeSort(a[mid:n])
    i=0
    j=0
    b.append(float("inf"))
    c.append(float("inf"))
    for k in range(0,n):
        if b[i]<c[j]:
            a[k]=b[i]
            i+=1
        else:
            a[k]=c[j]
            j+=1
    return a

a=[2,5,3,8,6,7,1,4,9]
MergeSort (a)
print(a)

分治策略,先划分子序列,后归并排序

计算复杂度theta(nlog(n))

注意:非原址运算

 五、堆排序

def HeapAdjust(lst,k,n):
    while(2*k+1<n):
        j=2*k+1
        if j+1<n and lst[j]<lst[j+1]:
            j=j+1
        if lst[j]>lst[k]:
            lst[k],lst[j]=lst[j],lst[k]
            k=j
        else:
            break
    return lst

def HeapSort(lst):
    n=len(lst)
    for i in range(n//2-1,-1,-1):
        lst=HeapAdjust(lst,i,n)
    for i in range(n-1,0,-1):
        lst[0],lst[i]=lst[i],lst[0]
        lst=HeapAdjust(lst,0,i)
    return lst
a=[1,5,2,8,3,4,6,9,7]
HeapSort(a)
print(a)

代码注释:http://blog.csdn.net/zhangzhengyi03539/article/details/44889951

构建大根堆,然后堆顶元素与序列最后一个元素交换,序列长度减一,对堆顶元素构建大根堆

计算复杂度theta(nlogn)

我觉得这个算法还有可能改进的地方,因为每次堆顶元素与最后一个元素交换,而最后一个元素是大根堆叶子上的元素,也就是在这条支路中最小的元素,这样在重新对堆顶元素构建大根队的过程中需要迭代好多步骤。

 

六、快速排序

例子一:

def QuickSort(a,start,end):
    key=a[start]
    i=start+1
    j=end
    while i<j:
        while a[i]<=key and i<j:
            i+=1
        while a[j]>key and j>i-1:
            j-=1
        if i<j:
            a[i],a[j]=a[j],a[i]
    a[start],a[j]=a[j],a[start]
    if j-1>start:
        QuickSort(a,start,j-1)
    if j+1<end:
        QuickSort(a,j+1,end)
    return a
a=[1,5,2,8,3,4,6,9,7]
QuickSort(a,0,len(a)-1)
print(a)

例子二:

def QuickSort(a,start,end):
    key=a[end]
    i=start-1
    for j in range(start,end):
        if a[j]<key:
            i+=1
            a[i],a[j]=a[j],a[i]
    a[i+1],a[end]=a[end],a[i+1]
    if i>start:
        QuickSort(a,start,i)
    if i+2<end:
        QuickSort(a,i+2,end)
    return a
a=[1,5,2,8,3,4,6,9,7]
QuickSort(a,0,len(a)-1)
print(a)

分治策略,最好的情况当然是每次都是二分了

平均情况/期望情况:计算复杂度theta(nlogn)

最坏的情况:计算复杂度theta(n^2)

 对于例子二,考虑这样一种情况,输入序列最后一个是最大的,然后对j循环的时候每次都要执行交换操作。还有就是快速排序的随机化版本,每次从输入中随机挑选一个数与key所在的数交换,然后执行快速排序。


Part II List Struct Sort

#include <iostream>
using namespace std;

struct Node
{
	int val;
	Node * Next;
};

Node* MergeList(Node* root1, Node* root2)
{
	Node* root = new Node;
	Node*p = root, *p1 = root1, *p2 = root2;
	while ((p1!=NULL)&&(p2!=NULL))
	{
		if (p1->val <= p2->val)
		{
			p->Next = p1;
			p = p->Next;
			p1 = p1->Next;
		}
		else
		{
			p->Next = p2;
			p = p->Next;
			p2 = p2->Next;
		}
	}
	if (p1 != NULL)
		p->Next = p1;
	else
		p->Next = p2;
	p = root->Next;
	delete root;
	return p;
}

Node* MergeSort(Node* root)
{
	if ((root == NULL) || (root->Next == NULL))
		return root;

	int length = 0;
	Node*p = root;
	while (p!=NULL)
	{
		length++;
		p = p->Next;
	}
	
	p = root;
	Node *root2;
	for (int i = 0; i < length / 2-1; i++)
	{
		p = p->Next;
	}
	root2 = p->Next;
	p->Next = NULL;
	
	root = MergeSort(root);
	root2 = MergeSort(root2);
	
	root = MergeList(root, root2);
	
	return root;
}

int main()
{
	Node *p1 = new Node{ 6,NULL };
	Node *p2 = new Node{ 3,NULL };
	Node *p3 = new Node{ 9,NULL };
	Node *p4 = new Node{ 7,NULL };
	Node *p5 = new Node{ 1,NULL };
	Node *p6 = new Node{ 2,NULL };
	Node *p7 = new Node{ 4,NULL };
	p1->Next = p2;
	p2->Next = p3;
	p3->Next = p4;
	p4->Next = p5;
	p5->Next = p6;
	p6->Next = p7;

	Node*p = p1;
	while (p != NULL)
	{
		cout << p->val << " ";
		p = p->Next;
	}
	cout << endl;

	p1 = MergeSort(p1);

	p = p1;
	while (p!=NULL)
	{
		cout << p->val << " ";
		p = p->Next;
	}
	cout << endl;
    return 0;
}


Part II List Struct Sort
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值