zoukankan      html  css  js  c++  java
  • Selection Sort

    选择排序(Selection Sort)也是一种比较简单的排序算法。

    基本思想

    找到数组中最小的那个元素,将其与数组的第一个元素交换位置;
    在剩下的元素中找到最小的元素,将其与数组中的第二个元素交换位置。
    即不断地选择剩余元素中的最小值。

    实现

    #include <stdio.h>
    
    #define MAXSIZE 100
    
    typedef struct
    {
    	int a[MAXSIZE + 1];  //a[1]~a[MAXSIZE]存储元素
    	int length;
    }Sqlist;
    
    
    void swap(Sqlist* L, int i, int j)
    {
    	int temp = L->a[i];
    	L->a[i] = L->a[j];
    	L->a[j] = temp;
    }
    
    /*升序排列*/
    void Sele_Sort(Sqlist* L)
    {
    	for (int i = 1; i < L->length; i++)
    	{
    	    //将a[i]和a[i+1...N]中最小的元素交换
    		int min = i;        //最小元素的索引
    		for (int j = i + 1; j <= L->length; j++)
            if (L->a[j] < L->a[min])
            {
                    min = j;
            }
            swap(L,i,min);
    	}
    }
    
    int main(int argc, char** argv)
    {
    	Sqlist L;
    
    	scanf("%d", &(L.length));
    	for (int i = 1; i <= L.length; i++)
    		scanf("%d", &(L.a[i]));
    
    	Sele_Sort(&L);
    
    	for (int i = 1; i <= L.length; i++)
    		printf("%d ", L.a[i]);
    	printf("
    ");
    
    	return 0;
    }
    
    

    复杂度

    选择排序需要N次交换以及(frac{N^2}{2})次比较,数据移动次数与数组大小呈线性关系,移动次数是最少的。
    时间复杂度(O(n^2))

    堆排序

    将顺序表看做一棵完全二叉树,大根堆就是父结点值大于两孩子结点,所以根结点存放最大值。
    构造初始堆需要从最后一个非叶结点的子树开始,向下筛选,如果根结点值小于孩子结点,将根结点值与(max(左孩子,右孩子))交换:

    建好堆后,输出堆顶元素即为最大值,通常将堆底元素送入堆顶,此时破坏了大根堆性质,将堆顶元素向下调整,保持大根堆:

    //parent->要下沉元素下标
    void Adjustdown(int* A, int len, int parent)
    {
    	int tmp = A[parent];  //保存要下沉的元素
    
    	for (int child = 2 * parent + 1; child < len; child = 2 * parent + 1)
    	{
    		//如果右孩子存在且比左孩子大,定位到右孩子
    		if (child + 1 < len && A[child] < A[child + 1])
    		{
    			child++;
    		}
    
    		//父结点大于孩子结点,下沉结束
    		if (A[child] <= tmp)
    			break;
    
    		//将孩子调整到父结点
    		A[parent] = A[child];
    		parent = child;  //修改parent以便继续向下筛选
    	}
    
    	A[parent] = tmp; //将被筛选的结点放在最终位置
    }
    
    //构建二叉堆
    void BuildMaxHeap(int* A, int len)
    {
    	//从最后一个非叶结点开始,向上调整
    	for (int i = len / 2 - 1; i >= 0; i--)
    	{
    		Adjustdown(A, len, i);
    	}
    }
    
    int* Heapsort(int* A, int len)
    {
    	BuildMaxHeap(A, len);
    	//从小到大排序
    	for (int i = len - 1; i >= 0; i--)
    	{
    		swap(A[0], A[i]);  //把堆顶元素与最后一个元素交换
    		Adjustdown(A, i, 0);  //将剩余的元素整理成堆
    	}
    
    	return A;
    }
    

    性能:建立初始堆(O(n)),每次向下调整的复杂度(O(h)),共有(n-1)次调整,故时间复杂度(O(nlogn))
    一般求前(K)大元素都采用堆排序,因为只需要调整(K)次,故(O(nlogK)),而快排要将所有元素排完后才能取出前(K)个。

  • 相关阅读:
    linux 中rz sz 文件传输
    linux find 命令
    深度学习的博客
    cifar10数据的转换、代码解释
    gflags的使用实例(转载)
    leveldb使用 (转载)
    (转载+整理)Leveldb安装及例子
    2013-09-25-【随笔】-Roy
    2013-09-22 [随笔]-Roy
    2013-08-12【随笔2】-Roy
  • 原文地址:https://www.cnblogs.com/EIMadrigal/p/12129755.html
Copyright © 2011-2022 走看看