排序算法(C语言+Python版)宝宝再也不怕面试官写排序算法了

直接插入排序

过程:
1. 数据可分看成两个部分,前面的数据是有序的
2. 从后面的数据取出一个元素,插到前面有序数据的合适位置
从右端开始查找,到找到比此元素大的时候,则此元素向后移动,以空出多余的空间来插入此元素。
3. 查找至最后。

例:
3 2 4 5 8 1
2 3 4 5 8 1
1 2 3 4 5 8

def insert_sort(lists):
    count = len(lists)

    for i in range(1, count):
        tmp = lists[i]
        j = i - 1
        while j >= 0 and lists[j]>tmp:
            lists[j+1] = lists[j]
            j -= 1

        lists[j+1] = tmp
    return lists
void direct_insert_sort(int *ar, int count);

void direct_insert_sort(int *ar, int count){
	int tmp;
	int i;
	int j;

	for (i=1; i < count; i++){
		tmp = ar[i];
		j = i-1;
		while(j>=0 && (ar[j] > tmp) ){
			ar[j+1] = ar[j];
			j--;
		}
		ar[j+1] = tmp;
	}
}

  

希尔排序

过程:
1.将所有的数据分组为N/2;这样每组就有2个数据,利用直接插入排序。
2.将所有的数据分组为N/2*2; 每组就有4个数据,利用直接插入排序。
3.step大于等于1,最后再一次直接插入排序

评价:
1. 时间复杂度:n^1.25 或者 nlog2(n)
2. 非稳定
3. 插入排序对于“局部有序”有较好的表现

def shell_sort(lists):
	count = len(lists)
	step = count/2
	while step>0:
		for i in range(step, count, step):
			tmp = lists[i]
			j = i - step
			while j >= 0 and lists[j] > tmp:
				lists[j+step] = lists[j]
				j -= step
			lists[j+step] = tmp
		step/=2
	return lists

  

void inner_direct_insert_sort(int *ar, int count, int step);
void shell_sort(int *ar, int count);

void shell_sort(int *ar, int count){
	int step;
	for (step=count/2; step > 0; step/=2)
		inner_direct_insert_sort(ar, count, step);
}

// 调用插入排序,但是这里需要改变步长。
void inner_direct_insert_sort(int *ar, int count, int step){
	int tmp;
	int i;
	int j;

	for (i=step; i < count; i+=step){
		tmp = ar[i];
		j = i-step;
		while(j>=0 && (ar[j] > tmp) ){
			ar[j+step] = ar[j];
			j-=step;
		}
		ar[j+step] = tmp;
	}
}

冒泡排序:

哈哈最简单了

1. 从头开始,依次和自己后面的元素进行比较,交换

时间复杂度也很高O(N)

def bubble_sort(lists):
	count = len(lists)
	for i in range(0, count):
		for j in range(i+1, count)
			if lists[i] > lists[j]:
				lists[i], lists[j] = lists[j], lists[i]
	return lists

  

void bubble_sort(int *ar, int count);

void bubble_sort(int *ar, int count){
	int i;
	int j;
	int tmp;

	for(i=0; i<count; i++){
		for (j=i+1; j<count; j++){
			if(ar[i] > ar[j]){
				tmp = ar[i];
				ar[i] = ar[j];
				ar[j] = tmp;
			}
		}
	}
}

  

快速排序

过程:
1、基本的步骤
首先确定参考元素,参考元素左边是比参考元素小的元素,参考元素右边是比参考元素大的元素;
即参考元素把数据分成两部分
先设参考

2、递归调用基本的步骤

评价:
时间复杂度:O(N*log2N)
稳定性:非稳定
如果第一个参考元素比后面的有多个元素大,则排序之后逆序
如果第一个参考元素比后面的有多个元素小,则排序之后顺序

最差情况:完全逆序、完全顺序

def quick_sort(lists, left, right):
    if left >= right:
        return lists

    tmp = lists[left]
    start = left
    end = right

    while left < right:
        while left < right and lists[right] > tmp:
            right -= 1
        lists[left] = lists[right]
        left += 1

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

        lists[right] = lists[left]
        right -= 1

    lists[left] = tmp

    quick_sort(lists, start, left-1)
    quick_sort(lists, left+1, end)
    return lists

l = [3,1,2,4,5,45,43,634534,5,4,4,324,5,2,4,32,4,5,422,52,42,42,421]
print quick_sort(l,0,len(l)-1)

  

int base_action(int *ar, int start_index, int end_index);
void inner_quick_sort(int *ar, int start_index, int end_index);
void quick_sort(int *ar, int count);

void quick_sort(int *ar, int count){
	inner_quick_sort(ar, 0, count-1);
}

void inner_quick_sort(int *ar, int start_index, int end_index){
	int mid_index;

	if(start_index < end_index){
		mid_index = base_action(ar, start_index, end_index);
		inner_quick_sort(ar, start_index, mid_index-1);
		inner_quick_sort(ar, mid_index+1, end_index);
	}
}

int base_action(int *ar, int start_index, int end_index){
	int tmp;

	tmp = ar[start_index];
	while(start_index < end_index){
		while(start_index < end_index && ar[end_index] > tmp){
			end_index--;
		}

		if(start_index < end_index){
			ar[start_index] = ar[end_index];
			start_index++;
		}

		while(start_index < end_index && ar[start_index] < tmp){
			start_index++;
		}

		if(start_index < end_index){
			ar[end_index] = ar[start_index];
			end_index--;
		}
	}
	ar[start_index] = tmp;

	return start_index;
}

  

直接选择排序
过程:
1. 先在所有的元素中选出最值,则当前的第一个元素交换,即放到有序的集合里面;
2. 再在后面剩余的元素中找出最值,放到之前的有序集合里面。注意,是放在有序集合的最右边;
2.1 选取下一个节点为参考元素,接着和剩余的元素作比较,选出最值的下标。
2.2 循环完成,就选择出了最值了。
2.3 检测最值的下标和之前的参考元素的下标是否相同,如果相同的话,说明中间并没有改变,
也就是说参考元素就是最值。
如果最值的下标和之前的参考元素的下标不同,则交换元素。

评价:
1. 时间复杂度:O( (1+n-1)n/2) ==>O(n*n)
2. 非稳定的
3. 完全升序,交换次数最少
4. 完全逆序,交换次数不是最多;

def select_sort(lists):
    count = len(lists)
    for i in range(0, count):
        min_index = i
        for j in range(i+1, count):
            if lists[j] < lists[min_index]:
                min_index = j
        lists[i],lists[min_index] = lists[min_index], lists[i]

    return lists

  

void direct_select_sort(int *ar, int count);

void direct_select_sort(int *ar, int count){
	int tmp;		//用于交换的中间值
	int i;			//下一个要比较的元素,即参考元素
	int j;			//除了已排好序的集合和下一个元素,剩下的所有元素的都和下一个元素比较
	int minIndex;	     //最小的值的下标,将来放到已排好的元素中去

	for (i=0; i < count-1; i++){
		minIndex = i;
		for (j = i+1; j<count; j++){
			if(ar[j] < ar[minIndex] ){
				minIndex = j;
			}
		}
		if (minIndex != i){
			tmp = ar[minIndex];
			ar[minIndex] = ar[i];
			ar[i] = tmp;
 		}
	}
}

  

堆排序

过程:
1、将整个的数据,调整成大根堆。(大根堆:根节点大于左右节点,调整过程深度优先)
这里提下完全二叉树的性质
设总结点为count
叶子节点数量:(count+1)/2
非叶子节点数量: count - (count+1)/2 = (count-1)/2
最后一个非节点: (count-1)/2 - 1
2、将根节点和最后一个叶子节点交换。之后再次调整整棵数为大根堆
3、直到只有一个根节点

评价:
1. 非稳定
2. O(N·log2N)
3. 完全顺序:小跟堆,最差情况
4. 完全逆序:大根堆,比较次数不变。最优情况

def adjust_head(lists, root, count):
    not_finished = True

    while not_finished and root <= (count-1)/2:
        max_index = root
        left_child  = 2*root + 1
        right_child = 2*root + 2
        if left_child < count and lists[left_child] > lists[max_index]:
            max_index = left_child
        if right_child < count and lists[right_child] > lists[max_index]:
            max_index = right_child
        if root != max_index:
            lists[root], lists[max_index] = lists[max_index], lists[root]
        else:
            not_finished = False
        root = max_index    

def heap_sort(lists):
    count = len(lists)
    last_not_leaf_node = (count-1)/2
    for root in range(last_not_leaf_node, -1, -1):
        adjust_head(lists, root,count)                            #调整为大跟堆
    while count > 1:
       lists[count-1], lists[0] = lists[0], lists[count-1]
       count -= 1
       adjust_head(lists,root, count)
    return lists

  

void adjustBigHeap(int *ar, int count, int root);
void heapSort(int *ar, int count);

void heapSort(int *ar, int count){
	int root;
	int tmp;

	for(root = (count-1)/2-1; root > 0; root--){
		adjustBigHeap(ar, count, root);
	}

	while(count > 1){
		adjustBigHeap(ar, count, root);
		tmp = ar[0];
		ar[0] = ar[count-1];
		ar[count-1] = tmp;
		count--;
	}
}

void adjustBigHeap(int *ar, int count, int root){
	int maxIndex;
	int tmp;
	boolean finished = FALSE;

	while(!finished && maxIndex < (count-1)/2){
		maxIndex = 2*root+1 < count && ar[2*root+1] > ar[root] ? 2*root+1 : root;
		maxIndex = 2*root+2 < count && ar[2*root+2] > ar[maxIndex] ? 2*root+2 : maxIndex;

		if(maxIndex != root){
			tmp = ar[root];
			ar[root] = ar[maxIndex];
			ar[maxIndex] = tmp;
		}else{
			finished = TRUE;
		}
		root = maxIndex;
	}
}

 等待更新。。。。。

时间: 2024-10-08 07:02:15

排序算法(C语言+Python版)宝宝再也不怕面试官写排序算法了的相关文章

【深度】扒开V8引擎的源码,我找到了你们想要的前端算法(下次面试官再问算法,用它怼回去!)

算法对于前端工程师来说总有一层神秘色彩,这篇文章通过解读V8源码,带你探索`Array.prototype.sort`函数下的算法实现. 来,先把你用过的和听说过的排序算法都列出来: * 快速排序 * 冒泡排序 * 插入排序 * 归并排序 * 堆排序 * 希尔排序 * 选择排序 * 计数排序 * 桶排序 * 基数排序 * ... 答题环节到了, sort 函数使用的以上哪一种算法? 如果你在网上搜索过关于 sort 源码的文章,可能会告诉你数组长度小于10用插入排序,否则用快速排序. 开始我也是

算法(第4版)-1.5 案例研究:union-find算法

问题→ 动态连通性:当程序从输入中读取了整数对p q时,如果已知的所有整数对都不能说明p和q是相连的,那么则将这一对整数写入到输出中.如果已知的数据可以说明p和q 是相连的,那么程序应该忽略p q这对整数并继续处理输入中的下一对整数. 该问题的应用→ 网络,变量名等价性,数字集合等. 设计API→ public class UF   UF(int N) 以整数标识(0到N-1)初始化N个触点 void union(int p, int q) 在p和q之间添加一条连接 int find(int p

数论算法——信息安全数学基础算法总结(python版)

/* Author: wsnpyo Update Date: 2014-11-16 Algorithm: 快速幂/Fermat, Solovay_Stassen, Miller-Rabin素性检验/Exgcd非递归版/中国剩余定理 */ import random def QuickPower(a, n, p): # 快速幂算法 tmp = a ret = 1 while(n > 0): if (n&1): ret = (ret * tmp) % p tmp = (tmp * tmp) %

Java的四种引用类型史上最详细,再也不怕面试官

Java四种引用类型 1.引用的基本概念 强引用:当我们使用new创建对象时,被创建的对象就是强引用,如Object object = new Object(),其中的object就是一个强引用了.如果一个对象具有强引用,JVM就不会去GC它,JVM宁可会报OOM来终止程序,也不回收该对象. 软引用: 如果一个对象只具备软引用,如果内存空间足够,那么JVM就不会GC它,如果内存空间不足了,就会GC该对象. 弱引用: 如果一个对象只具有弱引用,只要JVM的GC线程检测到了,就会立即回收.弱引用的生

人脸验证算法Joint Bayesian详解及实现(Python版)

人脸验证算法Joint Bayesian详解及实现(Python版) Tags: JointBayesian DeepLearning Python 本博客仅为作者记录笔记之用,不免有很多细节不对之处. 还望各位看官能够见谅,欢迎批评指正. 博客虽水,然亦博主之苦劳也. 如对代码有兴趣的请移步我的 Github. 如需转载,请附上本文链接,不甚感激!  http://blog.csdn.net/cyh_24/article/details/49059475 Bayesian Face Revis

排序算法——C#语言版

插入排序:(直接插入排序&希尔排序) using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Sort { public class InsertSort { public static int k; /// <summary> /// 直接插入排序 /// </summary> /// <param name="a&quo

[转] Twitter的分布式自增ID算法Snowflake实现分析及其Java、Php和Python版

转载自:http://www.dengchuanhua.com/132.html 在分布式系统中,需要生成全局UID的场合还是比较多的,twitter的snowflake解决了这种需求,实现也还是很简单的,除去配置信息,核心代码就是毫秒级时间41位+机器ID 10位+毫秒内序列12位. 该项目地址为:https://github.com/twitter/snowflake是用Scala实现的. python版详见开源项目https://github.com/erans/pysnowflake.

使用Apriori算法和FP-growth算法进行关联分析(Python版)

===================================================================== <机器学习实战>系列博客是博主阅读<机器学习实战>这本书的笔记也包含一些其他python实现的机器学习算法 算法实现均采用python github 源码同步:https://github.com/Thinkgamer/Machine-Learning-With-Python ==================================

“《算法》第4版第2章‘排序’”:初级排序算法(选择、冒泡、插入、希尔)

<算法>第4版作者是Robert Sedgewick 和 Kevin Wayne. 1. 选择排序 选择排序可以说是最简单的排序方法.首先,找到数组中最小的那个元素:其次,将它与数组的第一个元素交换位置(如果第一个元素就是最小元素,那么它就和自己交换):再次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置.如此往复,直到将整个数组排序. 该书中提出一个命题:对于长度为N的数组,选择排序需要大约N2/2次比较和N次交换.  程序如下: 1 void SelectionSort::s