堆排序算法分析(C语言版)
堆排序法c语言代码

堆排序法c语言代码堆排序法是一种常用的排序算法,它的特点是时间复杂度为O(nlogn),适用于大数据量的排序。
下面是使用C语言实现的堆排序算法。
1.原理堆排序法的基本思想是将待排序的序列构成一棵完全二叉树,并满足每个节点的值都大于/小于其子节点的值。
首先需要构建一个最大堆顶,将数组的首位和最后一个元素交换,然后将序列长度减一,再将已排序的序列构建堆顶,交换首位元素,以此类推,直到序列长度为一。
最终得到的排序序列就是按照升序或降序排列的。
2.实现#include <stdio.h>#include <stdlib.h>void head_adjust(int arr[], int start, int end);void heap_sort(int arr[], int len);int main(){int arr[] = {5, 9, 1, 4, 2, 8, 0, 3, 6, 7};int len = sizeof(arr) / sizeof(arr[0]);heap_sort(arr, len);for(int i=0; i<len; i++){printf("%d ", arr[i]);}return 0;}/*建立大根堆*/void head_adjust(int arr[], int start, int end){int dad = start;int son = dad*2 + 1;while(son <= end){if(son + 1 <= end && arr[son] < arr[son+1]) {son++;}if(arr[dad] > arr[son]){return;}else{int temp = arr[dad];arr[dad] = arr[son];arr[son] = temp;dad = son;son = dad*2 + 1;}}}/*堆排序*/void heap_sort(int arr[], int len) {for(int i = len/2-1; i>=0; i--) {head_adjust(arr, i, len-1); }for(int i =len-1; i>0; i--){int temp = arr[i];arr[i] = arr[0];arr[0] = temp;head_adjust(arr, 0, i-1);}}3.算法分析时间复杂度:O(nlogn)空间复杂度:O(1)稳定性:不稳定排序方法(可能会交换值相同的元素的相对位置)堆排序法适合数据量较大的排序任务,但在数据量较小时,实现的效率不如插入排序或快速排序。
C语言--常见排序算法

49
2 j 49
08
0
25* 3 49 25
16 4
21
5
08
25
25*
16
21
i k 49
j 25* 25
08
25
25*
16
21
算法实例:
1.1.5 选择排序
49 2
08 0
25 1 i
25* 3
16 4 k
21 5 j 21 16
k 指示当前序列中最小者
算法实现:
08 5 temp
16 21 25 25* 49 08 0 1 2 3 4 5
算法实现:
1.1.3 直接插入排序
void InsertSort (int r[ ], int n ) { // 假设关键字为整型,放在向量r[]中 int i, j, temp; for (i = 1;i< n;i++ ) { temp = r[i]; for(j = i;j>0;j- -) {//从后向前顺序比较,并依次后移 if ( temp < r[j-1] ) r[j] = r[j-1]; else break; } r[j] = temp; } }
输入n 个数给a[1] 到 a[n]
for j=1 to n-1
for i=1 to n-j
真 a[i]>a[i+1]
a[i]a[i+1]
输出a[1] 到 a[n]
main() { int a[11],i,j,t; printf("Input 10 numbers:\n"); for(i=1;i<11;i++) scanf("%d",&a[i]); printf("\n"); 假 for(j=1;j<=9;j++) for(i=1;i<=10-j;i++) if(a[i]>a[i+1]) {t=a[i]; a[i]=a[i+1]; a[i+1]=t;} printf("The sorted numbers:\n"); for(i=1;i<11;i++) printf("%d ",a[i]); }
C语言实现插入排序、归并排序、堆排序

插入排序、归并排序、堆排序的C实现。
如有疑问请联系QQ:631785485,我们一起学习。
1.插入排序/******************************************Insert_sort.cpp*实现对输入的数进行快速排序******************************************/#include <stdio.h>#include <stdlib.h>#define M 100void Quick_asc(int *a,const int size);void Quick_desc(int *a,const int size);void output(const int *a,const int size);int main(void){int a[]={9,8,7,6,5,4,3,2,1,0};int size;char quit;char c;size=sizeof(a)/sizeof(int);printf("\n************测**********试**************\n");printf("* 排序前:");output(a,size);printf("* 升序:");Quick_asc(a, size);output(a,size);printf("* 降序:");Quick_desc(a, size);output(a,size);printf("********测*****试*****结*****束*********\n\n");/***********************************//***************自输入模块**********//***********************************/do{printf("\n*************************输入************************\n");printf("提示:请输入要排序的数;中间用空格隔开;回车结束输入!\n\n>");int b[M];volatile int i=0;while((0==i || getchar()!='\n')){scanf("%d",&b[i++]);}printf("\n****************************************");printf("\n排序前:");output(b,i);printf("\n升序:");Quick_asc(b,i);output(b,i);printf("\n降序:");Quick_desc(b,i);output(b,i);printf("****************************************\n");printf("\n按任意键继续!Q键退出!\n>");quit=getchar();while(c=getchar()!='\n' && c!=EOF);system("cls");}while(quit!='Q' && 'q'!=quit);return 0;}//end main//自定义输出函数void output(const int *a,const int size){for(int k=0; k<size; k++){printf("%d ",*(a+k));}printf("\n");}//升序排列void Quick_asc(int *a,const int size){int key;int i, j;for(j=1; j<size; j++){key=*(a+j);i=j-1;while(i>=0 && *(a+i)>key){*(a+i+1)=*(a+i);--i;}*(a+i+1)=key;}}//降序排列void Quick_desc(int *a,const int size) {int key;int i, j;for(j=1; j<size; j++){key=*(a+j);i=j-1;while(i>=0 && *(a+i)<key){*(a+i+1)=*(a+i);--i;}*(a+i+1)=key;}}2.归并排序/************************************Merge_sort.cpp*归并排序的实现************************************/#include <stdio.h>#include <stdlib.h>#define M 100void output(const int *a,const int size); void merge(int *a, int p, int q, int r); void merge_sort(int *a, int p1, int r1); int main(){int a[]={9,8,7,6,5,4,3,2,1,0};char c;int size;size=sizeof(a)/sizeof(int);//归并排序printf("*******************归并排序测试*****************\n");printf("排序前:");output(a,size);merge_sort(a,0,size-1);//归并排序函数调用printf("排序后:");output(a,size);/*******************************************自定义输入模块******************************************/while(true){printf("******************************************************\n" );printf("提示:请输入要排序的数;中间用空格隔开;回车结束输入!\n\n>");int b[M];int i=0;while(0==i || (c=getchar())!='\n'){if(!(scanf("%d",&b[i++]))){i=0;printf("输入有误,请重新输入!");system("pause");system("cls");while(c=getchar()!='\n' && c!=EOF);printf("******************************************************\n" );printf("提示:请输入要排序的数;中间用空格隔开;回车结束输入!\n\n>");continue;}}printf("排序前:");output(b,i);printf("排序后:");merge_sort(b,0,i-1);output(b,i);printf("\n******************************************************\ n");printf("按Q退出,任意键继续!\n>");if((c=getchar())=='Q'||c=='q'){exit(0);}else{//清空输入流while(c=getchar()!='\n' && c!=EOF);}system("cls");}return 0;}//end main()void output(const int *a,const int size){for(int k=0; k<size; k++){printf("%d ",*(a+k));}printf("\n");}//归并排序二分void merge_sort(int *a, int p, int r){if(p<r){int q=(p+r)/2;merge_sort(a, p, q);merge_sort(a, q+1, r);merge(a, p, q, r);}}//end merge_sort()//归并排序//a为数的首地址,p为数的起始位置,q二分的位置,r结束的位置。
数组排序c语言数组排序方法

数组排序c语言数组排序方法在C语言中,可以使用多种排序算法对数组进行排序。
常见的排序算法包括冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等。
下面将详细介绍这些排序算法的原理、实现以及时间复杂度。
1. 冒泡排序(Bubble Sort):冒泡排序是一种简单的排序算法,其基本思想是重复地在相邻的元素之间进行比较和交换,将最大的元素逐渐“浮”到数组的尾部。
具体实现过程如下:cvoid bubbleSort(int arr[], int n) {for (int i = 0; i < n-1; i++) {for (int j = 0; j < n-1-i; j++) {if (arr[j] > arr[j+1]) {交换相邻元素int temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}}冒泡排序的时间复杂度为O(n^2),其中n为数组长度。
2. 选择排序(Selection Sort):选择排序也是一种简单的排序算法,其基本思想是每次从未排序的部分中选取最小(或最大)的元素,放到已排序部分的末尾。
具体实现过程如下:cvoid selectionSort(int arr[], int n) {for (int i = 0; i < n-1; i++) {int minIndex = i;for (int j = i+1; j < n; j++) {if (arr[j] < arr[minIndex]) {minIndex = j;}}将最小元素交换到已排序部分的末尾int temp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = temp;}选择排序的时间复杂度为O(n^2)。
3. 插入排序(Insertion Sort):插入排序的基本思想是将数组分为已排序和未排序两部分,每次从未排序部分选择一个元素,插入到已排序部分的正确位置。
C语言常用算法总结

C语言常用算法总结1、冒泡排序算法:冒泡排序是一种简单的排序算法,它重复地遍历要排序的序列,一次比较两个相邻的元素如果他们的顺序错误就把他们交换过来。
时间复杂度为O(n^2)。
2、快速排序算法:快速排序是一种基于分治的排序算法,通过递归的方式将数组划分为两个子数组,然后对子数组进行排序最后将排好序的子数组合并起来。
时间复杂度为O(nlogn)。
3、插入排序算法:插入排序是一种简单直观的排序算法,通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描找到相应位置并插入。
时间复杂度为O(n^2)。
4、选择排序算法:选择排序是一种简单的排序算法,每次循环选择未排序部分的最小元素,并放置在已排序部分的末尾。
时间复杂度为O(n^2)。
5、归并排序算法:归并排序是一种稳定的排序算法,基于分治思想,将数组递归地分为两个子数组,将子数组排序后再进行合并最终得到有序的数组。
时间复杂度为O(nlogn)。
6、堆排序算法:堆排序是一种基于完全二叉堆的排序算法,通过构建最大堆或最小堆,然后依次将堆顶元素与末尾元素交换再调整堆,得到有序的数组。
时间复杂度为O(nlogn)。
7、二分查找算法:二分查找是一种在有序数组中查找目标元素的算法,每次将待查找范围缩小一半,直到找到目标元素或范围为空。
时间复杂度为O(logn)。
8、KMP算法:KMP算法是一种字符串匹配算法,通过利用模式字符串的自重复性,避免不必要的比较提高匹配效率。
时间复杂度为O(m+n),其中m为文本串长度,n为模式串长度。
9、动态规划算法:动态规划是一种通过将问题分解为子问题,并通过组合子问题的解来求解原问题的方法。
动态规划算法通常使用内存空间来存储中间结果,从而避免重复计算。
时间复杂度取决于问题规模。
10、贪心算法:贪心算法是一种通过选择局部最优解来构建全局最优解的算法并以此构建最终解。
时间复杂度取决于问题规模。
11、最短路径算法:最短路径算法用于求解图中两个节点之间的最短路径,常见的算法包括Dijkstra算法和Floyd-Warshall算法。
C语言八大排序算法

C语⾔⼋⼤排序算法C语⾔⼋⼤排序算法,附动图和详细代码解释!来源:C语⾔与程序设计、⽵⾬听闲等⼀前⾔如果说各种编程语⾔是程序员的招式,那么数据结构和算法就相当于程序员的内功。
想写出精炼、优秀的代码,不通过不断的锤炼,是很难做到的。
⼆⼋⼤排序算法排序算法作为数据结构的重要部分,系统地学习⼀下是很有必要的。
1、排序的概念排序是计算机内经常进⾏的⼀种操作,其⽬的是将⼀组“⽆序”的记录序列调整为“有序”的记录序列。
排序分为内部排序和外部排序。
若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序。
反之,若参加排序的记录数量很⼤,整个序列的排序过程不可能在内存中完成,则称此类排序问题为外部排序。
2、排序分类⼋⼤排序算法均属于内部排序。
如果按照策略来分类,⼤致可分为:交换排序、插⼊排序、选择排序、归并排序和基数排序。
如下图所⽰:3、算法分析1.插⼊排序*直接插⼊排序*希尔排序2.选择排序*简单选择排序*堆排序3.交换排序*冒泡排序*快速排序4.归并排序5.基数排序不稳定排序:简单选择排序,快速排序,希尔排序,堆排序稳定排序:冒泡排序,直接插⼊排序,归并排序,奇数排序1、插⼊排序将第⼀个和第⼆个元素排好序,然后将第3个元素插⼊到已经排好序的元素中,依次类推(插⼊排序最好的情况就是数组已经有序了)因为插⼊排序每次只能操作⼀个元素,效率低。
元素个数N,取奇数k=N/2,将下标差值为k的数分为⼀组(⼀组元素个数看总元素个数决定),在组内构成有序序列,再取k=k/2,将下标差值为k的数分为⼀组,构成有序序列,直到k=1,然后再进⾏直接插⼊排序。
3、简单选择排序选出最⼩的数和第⼀个数交换,再在剩余的数中⼜选择最⼩的和第⼆个数交换,依次类推4、堆排序以升序排序为例,利⽤⼩根堆的性质(堆顶元素最⼩)不断输出最⼩元素,直到堆中没有元素1.构建⼩根堆2.输出堆顶元素3.将堆低元素放⼀个到堆顶,再重新构造成⼩根堆,再输出堆顶元素,以此类推5、冒泡排序改进1:如果某次冒泡不存在数据交换,则说明已经排序好了,可以直接退出排序改进2:头尾进⾏冒泡,每次把最⼤的沉底,最⼩的浮上去,两边往中间靠16、快速排序选择⼀个基准元素,⽐基准元素⼩的放基准元素的前⾯,⽐基准元素⼤的放基准元素的后⾯,这种动作叫分区,每次分区都把⼀个数列分成了两部分,每次分区都使得⼀个数字有序,然后将基准元素前⾯部分和后⾯部分继续分区,⼀直分区直到分区的区间中只有⼀个元素的时候,⼀个元素的序列肯定是有序的嘛,所以最后⼀个升序的序列就完成啦。
c语言 n个数值选出最大m个数 最优算法

c语言 n个数值选出最大m个数最优算法选择最大的n个数的问题在计算机科学领域中是一个经典的算法问题。
在本文中,我们将探讨一种最优算法来解决这个问题,该算法称为"堆排序"。
堆排序是一种基于二叉堆的排序算法,它具有时间复杂度为O(nlogn)的优势。
在堆排序中,我们使用一个称为"堆"的数据结构来选择最大的m个数。
让我们了解一下堆是什么。
堆是一种完全二叉树,其中每个节点的值都大于或等于其子节点的值(称为"最大堆")或小于或等于其子节点的值(称为"最小堆")。
在我们的问题中,我们将使用最大堆。
现在,让我们来看看如何使用堆排序算法来选择最大的m个数。
步骤1:建立最大堆我们需要将给定的n个数构建成一个最大堆。
我们可以通过从下到上,从右到左地调整每个节点的位置来实现。
具体来说,我们从最后一个非叶子节点开始,依次将每个节点与其子节点进行比较,并交换位置,直到满足最大堆的条件。
步骤2:选择最大的m个数一旦我们建立了最大堆,我们就可以开始选择最大的m个数了。
我们可以通过从堆的根节点开始,依次将根节点与最后一个叶子节点进行交换,并将最大的数放在一个新的数组或列表中。
然后,我们将最后一个叶子节点从堆中删除,并重新调整堆,使其满足最大堆的条件。
我们重复这个过程m次,直到我们选择了最大的m个数。
步骤3:输出最大的m个数我们将输出我们选择的最大的m个数。
这些数将按照从大到小的顺序排列。
现在,我们来看一个具体的例子,以更好地理解堆排序算法。
假设我们有一个包含10个数的数组:[5, 20, 3, 8, 15, 12, 16, 7, 25, 10],我们要选择其中最大的3个数。
步骤1:建立最大堆我们将数组构建成一个最大堆。
通过比较每个节点与其子节点的值,并交换位置,我们可以得到以下的最大堆:[25, 20, 16, 10, 15, 12, 3, 7, 5, 8]步骤2:选择最大的3个数现在,我们从最大堆中选择最大的3个数。
用堆栈实现四则运算c语言

用堆栈实现四则运算c语言堆栈是一种常见的数据结构,它符合先进后出的原则。
在四则运算中,我们可以借助堆栈这种数据结构实现运算,方便高效,不易出错。
堆栈的实现包括两个基本操作:Push(入栈)和Pop(出栈)。
我们可以以此设计四则运算。
首先,我们需要将输入的四则运算表达式转换成后缀表达式。
后缀表达式也叫逆波兰表达式,相对于中缀表达式而言,运算符在后面,操作数在前面,这样方便计算机进行读取和计算。
例如:中缀表达式:5+3*2后缀表达式:5 3 2 * +将中缀表达式转换成后缀表达式,我们需要用到堆栈。
具体的实现方法是,从左向右遍历表达式,如果是数字,则直接输出;如果是符号,则将其与堆栈顶的符号进行比较,如果优先级高就入栈,否则不断将符号出栈并输出,直到当前符号优先级大于堆栈顶符号优先级,最后将当前符号入栈。
例如:表达式:5+3*2堆栈操作:1.将5输出,堆栈为空2.遇到+号,入栈3.将3输出,堆栈顶为+号4.遇到*号,入栈5.将2输出,堆栈顶为*号6.输出*号,堆栈顶为+号7.输出+号,堆栈为空得到后缀表达式:5 3 2 * +有了后缀表达式,我们可以用堆栈进行计算。
具体方法是,从左向右遍历后缀表达式,如果是数字则入栈,如果是符号则将栈顶两个数字出栈并进行计算,将结果入栈,最终得到最终的计算结果。
例如:后缀表达式:5 3 2 * +堆栈操作:1.将5入栈2.将3入栈3.遇到*号,出栈3和2,进行计算得到6,将6入栈4.将栈顶元素5出栈5.遇到+号,出栈6和5,进行计算得到11,将11入栈得到计算结果:11通过堆栈实现四则运算,可以有效简化我们的计算流程,避免复杂的优先级判断和计算错误。
同时,堆栈为我们提供了一种更加高效的数据结构,不仅在四则运算中可以发挥作用,在其他应用中也很常见。
当然,在实际应用中,我们需要考虑到多种情况的处理,例如负数、小数、括号等,以及错误处理等细节问题,才能保证算法的正确性和可靠性。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
堆排序
堆排序是利用堆的性质进行的一种选择排序,下面先讨论一下堆。
1.堆
堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:
Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2]
即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。
堆分为大顶堆和小顶堆,满足Key[i]>=Key[2i+1]&&key>=key[2i+2]称为大顶堆,满足Key[i]<= key[2i+1]&&Key[i]<=key[2i+2]称为小顶堆。
由上述性质可知大顶堆的堆顶的关键字肯定是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的。
2.堆排序的思想
利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。
其基本思想为(大顶堆):
1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;
2)将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n];
3)由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。
不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
操作过程如下:
1)初始化堆:将R[1..n]构造为堆;
2)将当前无序区的堆顶元素R[1]同该区间的最后一个记录交换,然后将新的无序区调整为新的堆。
因此对于堆排序,最重要的两个操作就是构造初始堆和调整堆,其实构造初始堆事实上也是调整堆的过程,只不过构造初始堆是对所有的非叶节点都进行调整。
下面举例说明:
给定一个整形数组a[]={16,7,3,20,17,8},对其进行堆排序。
首先根据该数组元素构建一个完全二叉树,得到
然后需要构造初始堆,则从最后一个非叶节点开始调整,调整过程如下:
20和16交换后导致16不满足堆的性质,因此需重新调整,这样就得到了初始堆。
即每次调整都是从父节点、左孩子节点、右孩子节点三者中选择最大者跟父节点进行交换(交换之后可能造成被交换的孩子节点不满足堆的性质,因此每次交换之后要重新对被交换的孩子节点进行调整)。
有了初始堆之后就可以进行排序了。
此时3位于堆顶不满堆的性质,则需调整继续调整
这样整个区间便已经有序了。
从上述过程可知,堆排序其实也是一种选择排序,是一种树形选择排序。
只不过直接选择排序中,为了从R[1...n]中选择最大记录,需比较n-1次,然后从R[1...n-2]中选择最大记录需比较n-2次。
事实上这n-2次比较中有很多已经在前面的n-1次比较中已经做过,而树形选择排序恰好利用树形的特点保存了部分前面的比较结果,因此可以减少比较次数。
对于n个关键字序列,最坏情况下每个节点需比较log2(n)次,因此其最坏情况下时间复杂度为nlogn。
堆排序为不稳定排序,不适合记录较少的排序。
/*堆排序(大顶堆) 测试程序*/
#include <iostream>
#include<algorithm>
using namespace std;
void HeapAdjust(int *a,int i,int size) //调整堆
{
int lchild=2*i; //i的左孩子节点序号
int rchild=2*i+1; //i的右孩子节点序号
int max=i; //临时变量
if(i<=size/2) //如果i是叶节点就不用进行调整
{
if(lchild<=size&&a[lchild]>a[max])
{
max=lchild;
}
if(rchild<=size&&a[rchild]>a[max])
{
max=rchild;
}
if(max!=i)
{
swap(a[i],a[max]);
HeapAdjust(a,max,size); //避免调整之后以max为父节点的子树不是堆}
}
}
void BuildHeap(int *a,int size) //建立堆
{
int i;
for(i=size/2;i>=1;i--) //非叶节点最大序号值为size/2
{
HeapAdjust(a,i,size);
}
}
void HeapSort(int *a,int size) //堆排序
{
int i;
BuildHeap(a,size);
for(i=size;i>=1;i--)
{
//cout<<a[1]<<" ";
swap(a[1],a[i]);
//交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面
//BuildHeap(a,i-1); //将余下元素重新建立为大顶堆
HeapAdjust(a,1,i-1); //重新调整堆顶节点成为大顶堆
}
}
int main(int argc, char *argv[])
{
//int a[]={0,16,20,3,11,17,8};
int a[100];
int size;
while(scanf("%d",&size)==1&&size>0)
{
int i;
for(i=1;i<=size;i++)
cin>>a[i];
HeapSort(a,size);
for(i=1;i<=size;i++)
cout<<a[i]<<"";
cout<<endl;
}
return 0;
}。