• 排序算法(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^2)

    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
    		if left < right:
    			lists[left] = lists[right]
    			left += 1
    
    		while left < right and lists[left] < tmp:
    			left += 1
    		if left < right:
    			lists[right] = lists[left]
    			right -= 1
    	lists[left] = tmp
    
    	quick_sort(lists, start, left-1)
    	quick_sort(lists, left+1, end)
    	return lists
    

      

    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(count):
            min_index = i
            for j in range(i+1,count):
                if lists[j] < lists[min_index]:
                    min_index = j
            if min_index != i:
                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;
    	}
    }
    

    归并算法:分而治之

    1. 将所有的数一分为二,在把其中的一组再一分为二,如此反复,最后在将有序的数组合并

    2. 最关键的就是,递归终止的条件,即当每个组中只有一个元素。

    3. 最重要的就是处理怎么合并。假设左边有序的起点为i, 右边有序的起点为j。将左右两边的数组相互比较,如果左边小的话,将比较的元素放入到结果集中,同时i应该加1。

     如果右边元素大,则它放到结果集中,同时j要加1。如果左右两边其中的一边达到顶端(mid/end),则把另一组元素全部放到结果集中

    评价:

    平均情况   最坏情况     最好情况     空间复杂度
    O(nlog2n)  O(nlog2n)     O(nlog2n)   O(n)
    稳定

    def merge(left, right):
    	i, j = 0, 0 
    	rst = []
    	while i < len(left) and j < len(right):
    		if left[i] <= right[j]:
    			rst.append(left[i])
    			i += 1
    		else:
    			rst.append(right[j])
    			j += 1
    	rst += left[i:]
    	rst += right[j:]
    
    	return rst
    
    def merge_sort(lists):
    	if len(lists) <= 1:
    		return lists
    
    	middle = len(lists)/2
    	left  = merge_sort(lists[middle:])
    	right = merge_sort(lists[:middle])
    
    	return merge(left, right)
    void merge_sort(int *ar, int left, int right);
    void merge(int *ar, int left, int right);
    
    void merge_sort(int *ar, int left, int right){
    	int i;
    	if(left < right){
    		i = (left + right)/2;
    		merge_sort(a, left, i);
    		merge_sort(a, i+1, right);
    		merge(a, left, right);
    	}
    }
    
    void merge(int *ar, int left, int right){
    	int begin1 = left;
    	int mid = (left + right)/2;
    	int begin2 = mid+1;
    	int k = 0;
    	int new_ar_len = right - left + 1;
    	int *b = (int *)malloc(new_ar_len*sizeof(int));
    	while(begin1 <= mid && begin2 <= right){
    		if(ar[begin1] <= ar[begin2]){
    			b[k++] = ar[begin1++];
    		}else {
    			b[k++] = ar[begin2++];
    		}
    		while(begin1 <= mid)
    			b[k++] = ar[begin1++];
    		while(begin2 <= right)
    			b[k++] = ar[begin2++];
    		copy_array(b, a, new_ar_len, left);
    		free(b);
    	}
    }
    
    void copy_array(int *src, int *dst, int new_ar_len, int first){
    	int i;
    	int j=first;
    
    	for(i=0; i < len; i++){
    		dst[j] = src[i];
    		j++;
    	}
    }
    

    基数排序:

    将所有的数,按照各位进行排序并保持数组,接着按照十位排序,进行百位...

    桶的个数,应该是基数的大小

    进行比较的次数=所有元素最大数所占的位数

    def radix_sort(lists):
        for k in xrange(len(str(max(lists)))):
            bucket = [ [] for _ in xrange(10)]
            for i in lists:
                bucket[i / (10 ** k) % 10].append(i)
            lists = [element for item in bucket for element in item]
        return lists
    

      c语言我看着晕~

    直接交换排序

    过程:
    相邻的两个比较,交换;
    一轮比较之后,最后的一个数为最值(比较时使用'>',为升序,最后一个为最大值)
    下一比较,那么最后的数值就不需要比较。如m次比较,只需比较前面1,n-m-1之间的数
    但是如果在一次比较的过程中,没有交换数据,那么数值就已经排序完成了。这里借助了标志位来判断


    时间复杂度:O(n^2)
    稳定!
    最优:全为升序
    最差:全为逆序

      

    def exchange_sort(lists):
        count = len(lists)
        has_exchanged = True             #在比较的过程中,如果没有数字发生交换,那么说明数据已经有序的了。退出即可
     
        for i in range(0, count):
            for j in range(0, count-i-1):
                has_exchanged = False
                if lists[j] > lists[j+1]:
                    lists[j], lists[j+1] = lists[j+1], lists[j]
                    has_exchanged = True
            if not has_exchanged:
                break
    
        return lists
    

      

    void direct_change_sort(int *ar, int count){
    	int i;
    	int j;
    	int tmp;
    	unsigned char has_exchanged;
    
    	for(i=0; i<count && has_exchanged ; i++){
    		for(j=0,has_exchanged = 0; j<count-i; j++){
    			if(ar[j] > ar[j+1]){
    				tmp = ar[j+1];
    				ar[j+1] = ar[j];
    				ar[j] = tmp;
    				has_exchanged = 1;
    			}
    		}
    	}
    }
    

      

    偷张图:

  • 相关阅读:
    第一个ADO.NET连接SQl server数据库
    Mysql编码
    SNMP协议报文分析
    物理层计算
    随机产生数组
    c#排序
    c#计算一段代码的时间复杂度
    jwt认证
    drf三大组件之频率认证组件
    drf三大组件之认证组件与权限组件
  • 原文地址:https://www.cnblogs.com/wxl-dede/p/5325327.html
Copyright © 2020-2023  润新知