C语言排序算法之选择排序(直接选择排序,堆排序)

目录
  • 前言
  • 一、直接选择排序
    • 1.1 算法思想
    • 1.2 代码实现
    • 1.3 直接选择排序的特征总结
  • 二、堆排序
    • 2.1 什么是堆?
    • 2.2 判断是否是堆
    • 2.3 向下调整算法
    • 2.4 自底向上的建堆方式
    • 2.5 代码实现
    • 2.6 堆排序的特性总结
    • 2.7 堆排序的特性总结

前言

本期为大家带来的是常见排序算法中的选择排序,主要有直接选择排序以及——堆排序(有点难理解),包您一看就会,快来试试吧~

一、直接选择排序

1.1 算法思想

每一次从待排序的数据元素中选出最小(或最大的)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

在元素集合a[i]--a[n-1]中选择关键码最大(小)的数据元素 若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个) 元素交换 在剩余的 [a[i] , a[n-2] …… [a[i+1],a[n-1] ]集合中,重复上述步骤,直到集合剩 余1个元素。

我们拿一组实例来感受一下,直接选择排序是怎么运算的:

1.2 代码实现

给大家带来一个优化版本的直接选择排序,一次遍历,选出最大数和最小数,然后交换,相较于传统的,效率高了许多。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

//交换
void Swap(int* mini, int* maxi)
{
	int tmp = *mini;
	*mini = *maxi;
	*maxi = tmp;
}

//打印
void Print(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
}

//直接选择排序
void SelectSort(int *a,int n)
{
	//下标
	int begin = 0;
	int end = n - 1;
	while (begin < end)
	{
		int mini = begin, maxi = end;
		//选出最大的给maxi,选出最小的给mini
		for (int i=begin;i<=end;++i)
		{
			if (a[i]>a[mini])//升序
			{
				mini = i;   //改两个if的符号即可实现升序、降序转换。
			}
			if (a[i] <a[maxi])
			{
				maxi = i;
			}
		}
		//交换
		Swap(&a[begin],&a[mini]);
        //因为还有一种特殊情况,就是begin跟maxi重叠,然后执行第一次交换之后,maxi记录的是最小值
        if (begin == maxi)
		{
			maxi = mini;
		}
		Swap(&a[end], &a[maxi]);
		++begin;
		--end;
	}
}
直接选择排序
//void SelectSort(int* a, int n)//(升序)
//{
//	for (int j=0;j<n-1;j++)//整体遍历
//	{
//		for (int i=j+1;i<n;i++)//遍历比较
//		{
//			if (a[j] > a[i])//比较交换
//			{
//				int tmp = a[j];
//				a[j] = a[i];
//				a[i] = tmp;
//			}
//		}
//	}
//}
int main()
{
	int a[10] = { 3,5,9,7,4,2,1,6,0,8 };
	SelectSort(a, sizeof(a) / sizeof(a[0]));
	//打印
	Print(a, sizeof(a) / sizeof(a[0]));
	return 0;
}

1.3 直接选择排序的特征总结

  • 1.直接选择排序的算法非常好理解,但是效率不高,实际中也很少使用
  • 2.时间复杂度:O(N^2) ,直接选择排序不管数据的顺序如何,都要遍历至结束
  • 3.空间复杂度:O(1)
  • 4.稳定性:不稳定

二、堆排序

2.1 什么是堆?

2.2 判断是否是堆

我们在给到一个数组的时候,里面的数据往往不是“堆”,我们在使用堆排序的时候,就需要建堆,

堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种的排序算法,它是选择排序的一种,利用堆来进行选择数据。跟着我一起看看具体是怎么操作的。

建小堆排降序,建大堆排升序。

怎样建堆呢?这里我们的前辈就设计了一种算法

2.3 向下调整算法

堆排序的本质是选择排序

向下调整算法,如果是建小堆(排降序),前提:左右子树都是小堆。大堆就是反着来。

从根节点开始,选出左右孩子中小的那一个跟父亲比较,如果比父亲小就交换,然后继续往下调整,调整到叶子节点就停止。

2.4 自底向上的建堆方式

这种建堆方式是从倒数第二层的节点(叶子节点的上一层)开始,从右往左,从下到上的向下进行调整。

2.5 代码实现

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//打印数据
void Printf(int* a, int n)
{
	for (int i = 0; i < n; ++i)
	{
		printf("%d ", a[i]);
	}
}

//交换,传地址
void Swap(int* child, int* parent)
{
	int tmp = *child;
	*child = *parent;
	*parent = tmp;
}
//向下调整算法
//从根节点开始,如果是建立小堆选出左右孩子中小的那一个,跟父亲比较,如果比父亲小就交换
void AdjustDwon(int* a, int n, int root)//建小堆
{
	int parent = root;//父亲节点
	int child = parent * 2 + 1;//默认是左孩子
	while (child < n)//叶子节点下标不会超过数组总下标数n
	{
		//选出左右孩子中最小的那一个
		if (child+1 < n&& a[child + 1] < a[child])
		{
			child += 1;//用a[child]与父亲节点a[parent]比较
		}
		if (a[child] < a[parent])
		{
			//交换,传地址
			Swap(&a[child], &a[parent]);
			//交换后,将child,作为根节点继续向下调整,持续建堆
			parent = child;
			//新的左孩子
			child = parent * 2 + 1;
		}
		else
		{
			break;//如果不用交换,直接结束循环
		}
	}
}
//堆的建立
//大堆要求:树中所有的父亲都>=孩子,根是最大的
//小堆要求:书中所有的父亲都<=孩子,根是最小的
//建大堆排升序,建小堆排降序
//建堆的时间复杂度是O(N);
void HeapSort(int *a,int n)
{
	//找父亲节点
	for (int i=(n-1-1)/2;i>=0;--i)
	{
		//向下调整算法
		AdjustDwon(a,n,i);
	}
    //大堆或小堆建立完毕,排序
	//用主根节点与最后一个节点交换位置
	int end = n - 1;
	while (end>0)
	{
		//交换,传地址
		Swap(&a[0],&a[end]);
		//继续向下调整
		AdjustDwon(a,end,0);
		--end;
	}
}
//选择排序—堆排序
int main()
{
	int a[10] = {9,2,5,4,3,1,6,7,8,0};
	//堆的建立
	HeapSort(a,sizeof(a) / sizeof(a[0]));
	//打印数据
	Printf(a,sizeof(a) / sizeof(a[0]));
	return 0;
}

2.6 堆排序的特性总结

  • 1.堆排序使用堆来选数,效率高很多
  • 2.时间复杂度:O(N*logN)
  • 3.空间复杂度:O(1)
  • 4.稳定性:不稳定

2.7 堆排序的特性总结

  • 1.堆排序使用堆来选数,效率高很多
  • 2.时间复杂度:O(N*logN)
  • 3.空间复杂度:O(1)
  • 4.稳定性:不稳定

到此这篇关于C语言排序算法之选择排序(直接选择排序,堆排序)的文章就介绍到这了,更多相关C语言选择排序 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言对堆排序一个算法思路和实现代码

    算法思想简单描述: 堆排序是一种树形选择排序,是对直接选择排序的有效改进. 堆的定义如下:具有n个元素的序列(h1,h2,...,hn),当且仅当满足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,...,n/2)时称之为堆.在这里只讨论满足前者条件的堆. 由堆的定义可以看出,堆顶元素(即第一个元素)必为最大项.完全二叉树可以很直观地表示堆的结构.堆顶为根,其它为左子树.右子树. 初始时把要排序的数的序列看作是一棵顺序存储的二叉树,调整它们的

  • C语言选择排序算法及实例代码

    选择排序是排序算法的一种,这里以从小到大排序为例进行讲解. 基本思想及举例说明 选择排序(从小到大)的基本思想是,首先,选出最小的数,放在第一个位置:然后,选出第二小的数,放在第二个位置:以此类推,直到所有的数从小到大排序. 在实现上,我们通常是先确定第i小的数所在的位置,然后,将其与第i个数进行交换. 下面,以对 3  2  4  1 进行选择排序说明排序过程,使用min_index 记录当前最小的数所在的位置. 第1轮 排序过程 (寻找第1小的数所在的位置) 3  2  4  1(最初, m

  • C语言 选择排序算法详解及实现代码

    选择排序是排序算法的一种,这里以从小到大排序为例进行讲解. 基本思想及举例说明 选择排序(从小到大)的基本思想是,首先,选出最小的数,放在第一个位置:然后,选出第二小的数,放在第二个位置:以此类推,直到所有的数从小到大排序. 在实现上,我们通常是先确定第i小的数所在的位置,然后,将其与第i个数进行交换. 下面,以对 3  2  4  1 进行选择排序说明排序过程,使用min_index 记录当前最小的数所在的位置. 第1轮 排序过程 (寻找第1小的数所在的位置) 3  2  4  1(最初, m

  • C语言基本排序算法之插入排序与直接选择排序实现方法

    本文实例讲述了C语言基本排序算法之插入排序与直接选择排序实现方法.分享给大家供大家参考,具体如下: 声明待排序元素类型 /*-------------------------- typedef.h 方便修改待排序元素类型 -------------------------------------*/ #ifndef TYPEDEF_H #define TYPEDEF_H typedef int T; #endif 插入排序: /*---------------------------------

  • C语言实现堆排序的简单实例

    本文通过一个C语言实现堆排序的简单实例,帮助大家抛开复杂的概念,更好的理解堆排序. 实例代码如下: void FindMaxInHeap(int arr[], const int size) { for (int j = size - 1; j > 0; --j) { int parent = j / 2; int child = j; if (j < size - 1 && arr[j] < arr[j+1]) { ++child; } if (arr[child] &

  • C语言实现基于最大堆和最小堆的堆排序算法示例

    堆定义 堆实际上是一棵完全二叉树,其任何一非叶节点满足性质: Key[i]<=key[2i+1]&&Key[i]<=key[2i+2](小顶堆)或者:Key[i]>=Key[2i+1]&&key>=key[2i+2](大顶堆) 即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字. 堆排序的思想 利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单. 最大堆:所有节点的子节点比其

  • C语言实现各种排序算法实例代码(选择,冒泡,插入,归并,希尔,快排,堆排序,计数)

    目录 前言 选择排序 冒泡排序 插入排序 归并排序 希尔排序 快速排序 堆排序 计数排序 总结 前言 平时用惯了高级语言高级工具高级算法,难免对一些基础算法感到生疏.但最基础的排序算法中实则蕴含着相当丰富的优化思维,熟练运用可起到举一反三之功效. 选择排序 选择排序几乎是最无脑的一种排序算法,通过遍历一次数组,选出其中最大(小)的值放在新数组的第一位:再从数组中剩下的数里选出最大(小)的,放到第二位,依次类推. 算法步骤 设数组有n个元素,{ a 0 , a 1 , - , a n } 从数组第

  • C语言常见排序算法之插入排序(直接插入排序,希尔排序)

    目录 前言 一.直接插入排序 1.1 基本思想 1.2 算法思想 1.3 程序实现 1.4 直接插入排序的总结 二.希尔排序 2.1 算法思想 2.2 程序实现 2.3 希尔排序的特征总结 前言 本期为大家带来的是常见排序算法中的插入排序,主要有直接插入排序以及它的升级版——希尔排序,包您一看就会,快来试试吧~ 一.直接插入排序 1.1 基本思想 在生活当中,这种排序方式处处可见: 在玩扑克牌的时候我们就会采用插入排序的思想,当我们拿起第二张牌时,就会下意识的与第一张牌进行比较,如果比第一张牌小

  • C++实现八个常用的排序算法 插入排序、冒泡排序、选择排序、希尔排序等

    本文实现了八个常用的排序算法:插入排序.冒泡排序.选择排序.希尔排序 .快速排序.归并排序.堆排序和LST基数排序 首先是算法实现文件Sort.h,代码如下: /* * 实现了八个常用的排序算法:插入排序.冒泡排序.选择排序.希尔排序 * 以及快速排序.归并排序.堆排序和LST基数排序 * @author gkh178 */ #include <iostream> template<class T> void swap_value(T &a, T &b) { T t

  • C语言直接选择排序算法详解

    目录 1. 直接选择排序介绍 1.1 定义 1.2 基本原理 1.3 时间复杂度 1.4 空间复杂度 1.5 优缺点 2. 代码实现 2.1 代码设计 2.2 代码实现 1. 直接选择排序介绍 1.1 定义 直接选择排序是指每次都从剩余数据中选出最大或者最小的,将其排在已经排好的有序表后面. 1.2 基本原理 每次从无序表中选择最小(或最大)元素,将其作为首元素,知道所有元素排完为止.将一个有n个元素的数组从小到大排序,第一次从R[0] ~ R[n-1]中选取最小值,与R[0]交换,第二次从R[

  • C语言实现经典排序算法的示例代码

    目录 一.冒泡排序 1.原理 2.实现 3.算法分析 二.选择排序 1.原理 2.实现 3.算法分析 三.插入排序 1.原理 2.实现 3.算法分析 四.希尔排序 1.原理 2.实现 3.算法分析 总结 一.冒泡排序 1.原理 从数组的头开始不断比较相邻两个数的大小,不断将较大的数右移,一个循环后,最大数移至最后一位,无序数组规模减一.不断重复前面动作,知道数组完全有序. 2.实现 void swap(int* a, int* b) { int temp = *a; *a = *b; *b =

  • C语言常见排序算法之交换排序(冒泡排序,快速排序)

    目录 前言 1.交换排序——冒泡排序 1.1 算法思想 1.2 动图演示 1.3 冒泡最好的情况 2. 交换排序——快速排序 2.1 快速排序——挖坑法 快排的缺点 三数取中法 2.3 快速排序——左右指针法 2.4 前后指针法 前言 本期为大家带来的是常见排序算法中的交换排序,主要有冒泡排序,快速排序,快排分享了三种算法:挖坑法,左右指针法,前后指针法,以及两种优化方式:解决快排最坏情况的“三数取中”,避免递归次数过多的"小区间优化", 基本思想:所谓交换,就是根据序列中两个记录键值

  • java数据结构排序算法之树形选择排序详解

    本文实例讲述了java数据结构排序算法之树形选择排序.分享给大家供大家参考,具体如下: 这里我们就来说说选择类排序之一的排序:树形选择排序 在简单选择排序中,每次的比较都没有用到上次比较的结果,所以比较操作的时间复杂度是O(N^2),想要降低比较的次数,则需要把比较过程中的大小关系保存下来.树形选择排序是对简单选择排序的改进. 树形选择排序:又称锦标赛排序(Tournament Sort),是一种按照锦标赛的思想进行选择排序的方法.首先对n个记录的关键字进行两两比较,然后在n/2个较小者之间再进

  • java 合并排序算法、冒泡排序算法、选择排序算法、插入排序算法、快速排序算法的描述

    算法是在有限步骤内求解某一问题所使用的一组定义明确的规则.通俗点说,就是计算机解题的过程.在这个过程中,无论是形成解题思路还是编写程序,都是在实施某种算法.前者是推理实现的算法,后者是操作实现的算法. 一个算法应该具有以下五个重要的特征: 1.有穷性: 一个算法必须保证执行有限步之后结束: 2.确切性: 算法的每一步骤必须有确切的定义: 3.输入:一个算法有0个或多个输入,以刻画运算对象的初始情况: 4.输出:一个算法有一个或多个输出,以反映对输入数据加工后的结果.没有输出的算法是毫无意义的:

  • PHP排序算法之简单选择排序(Simple Selection Sort)实例分析

    本文实例讲述了PHP排序算法之简单选择排序(Simple Selection Sort).分享给大家供大家参考,具体如下: 基本思想: 通过 n - i 次关键字间的比较,从 n - i + 1 个记录中选出关键字最小的记录,并和第 i (1 <= i <= n) 个记录交换,执行n-1趟 后就完成了记录序列的排序. 算法实现: <?php //简单选择排序 //交换函数 function swap(array &$arr,$a,$b){ $temp = $arr[$a]; $a

  • PHP四种排序算法实现及效率分析【冒泡排序,插入排序,选择排序和快速排序】

    本文实例讲述了PHP四种排序算法实现及效率分析.分享给大家供大家参考,具体如下: PHP的四种基本排序算法为:冒泡排序.插入排序.选择排序和快速排序. 下面是我整理出来的算法代码: 1. 冒泡排序: 思路:对数组进行多轮冒泡,每一轮对数组中的元素两两比较,调整位置,冒出一个最大的数来. //简单版: function bubbleSort($arr) { $n = count($arr); for($i=1;$i<$n;$i++) { //冒泡的轮数(最多$n-1轮) for($j=0;$j<

随机推荐