读数据结构与算法分析

插入排序

核心:利用的是从位置0到位置P都是已排序的

所以从位置1开始排序,如果当前位置不对,则和前面元素反复交换重新排序

实现

void InsertionSort(ElementType A[], int N)
{
int i,P;
ElementType Tmp ;
for(P = 1;P < N;P++)
{
Tmp = A[P] ;
for(i = P;i > 0 && A[i-1] > Tmp;i--)
A[i] = A[i-1] ;
A[i] = Tmp ;
}
}


希尔排序

使用hk增量序列进行一趟排序后,对每个i都有

A[i] \leq A[i+hk]

重要性质:一个hk排序的文件在之后的排序中将保持hk排序性

实现

  • ht = [N / 2]
  • hk = [hk+1 / 2]
void ShellSort(ElmentType A[], int N)
{
ElementType Tmp ;
int i,j,Increment ;
for(Increment = N/2;Increment > 0;Increment /= 2)
for(i = Increment;i < N;i++)
{
Tmp = A[i] ;
for(j = i;j <= Increment;j -= Increment)
if(Tmp < A[j-Increment])
A[j] = A[j-Increment] ;
else
break ;
A[j] = Tmp ;
}
}

堆排序

基于原有的二叉堆

建立二叉堆,执行DeleteMax操作,储存至数组(节省空间可以倒序储存在当前数组)

实现

#define LeftChild(i) (2 * i + 1) ;
void Percdown(ElementType A[],int i,int N)
{
int Child ,i;
ElementType Tmp ;
for(Tmp = A[i]; LeftChild(i) < N-1;i = Child)
{
Child = LeftChild(i) ;
if(Tmp < A[Child])
A[i] = A[Chile] ;
else
break ;
}
A[i] = Tmp ;
} void HeapSore(ElementType A[],int N)
{
int i ;
for(i = N/2 ;i >= 0;i--)
Percdown(A,i,N) ; //建立二叉堆
for(i = N-1; i > 0; i--)
{
Swap(&A[0],&A[i]) ;
Percdown(A,0,i) ;
} }

归并排序

基本思想是合并两个已排序的表

实现

递归合并

void Msort(ElementType A[],ElementeType TmpArray[],int Left,int Right)
{
int Center ;
if(Left < Right)
{
Center = (Left + Right) /2 ;
Msort(A,TmpArray,Left,Right) ;
Msort(A,TmpArray,Center + 1,Right) ;
Merge(A,TmpArray,Left,Center + 1,Right) ;
}
}

驱动程序

void Mergesort(ElementType A[],int N)
{
ElementType *TmpArray ; TmpArray = malloc(N * sizeof(ElementType)) ;
if(TmpArray != NULL)
{
Msort(A,TmpArray,0,N-1) ;
free(TmpArray) ;
}
else
FatalError("内存不足") ;
}

合并函数

void Merge(ElementType A[],ElementType TmpArray[],int Lpos,int Rpos,int RightEnd)
{
int i,LeftEnd,NumElements,TmpPos ; LeftEnd = Rpos - 1;
TmpPos = Lpos ;
NumElement = RightEnd - Lpos + 1 ; while(Lpos <= LeftEnd && Rpos <= RightEnd)
if(A[Lpos] <= A[Rpos])
TmpArray[TmpPos++] = A[Lpos++] ;
else
TmpArray[TmpPos++] = A[Rpos++] ; while(Lpos <= LeftEnd)
TmpArray[TmpPos++] = A[Lpos++] ;
while(Rpos <= RightEnd)
TmpArray[TmpPos++] = A[Rpos++] for(i = 0;i < NumElement ;i++,RightEnd--)
A[RightEnd] = TmpArray[RightEnd] ;
}

快速排序

和归并排序一样都是分治递归算法,在小数组上效率并没有插入排序好

  1. 如果S中元素个数是0或1,则返回
  2. 取S中任一元素v,称为枢纽元
  3. 将S剩余的其它元素,分为两个不相交的集合
  4. 返回quicksort(S1),继续选择v,继续quicksort(S2) ;

实现

选取枢纽元

三数中值分割方法

ElementType Median3(ElementType A[],int Left,int Right)
{
int Center = (Left + Right) / 2 ; if(A[Left] > A[Center])
Swap(&A[Left],&A[Center]) ;
if(A[Left] > A[Right])
Swap(&A[Left],&A[Right]) ;
if(A[Center] > A[Right])
Swap(&A[Center],&A[Right]) ; Swap(&A[Center],&A[Right - 1]) ;
return A[Right - 1] ; }

主函数

#define Cutoff(3) ;

void Qsort(ElementType A[],int Left,int Right)
{
int i,j ;
ElementType Pivot ; if(Left + Cutoff <= Right)
{
Pivot = Midian3(A,Left,Right)
i = Left ; j = Right ;
for(;;)
{
While(A[++i] < Privot){}
While(A[--j] > Privot){}
if(i < j)
Swap(&A[i],&A[j]) ;
else
break ;
}
Swap(&A[i],&A[Right-1]) ; Qsort(A,Left,i-1) ;
Qsort(A,i+1,Right) ; }
else
InsertionSort(A + Left,Right - Left + 1) ;
}

驱动函数

void QuickSort(ElementType A[],int N)
{
Qsort(A,0,N-1) ;
}

总结

  • 对于一般的内部排序,选用的方法一般是插入排序、希尔排序和快速排序,根据输入来选择
  • 高度优化的快速排序在对于很少的输入也可能和希尔排序一样快

    对于快速排序,选取枢纽元十分关键

  • 堆排序比希尔排序要满
  • 插入排序一般用于较小的或接近排好序的输入
  • 归并排序在主存排序中不如快速排序那么好,但是合并时外部排序的中心思想

排序(C语言实现)的更多相关文章

  1. 选择排序_C语言_数组

    选择排序_C语言_数组 #include <stdio.h> void select_sort(int *); int main(int argc, const char * argv[] ...

  2. 计数排序(C语言版本)

    让我们来谈谈数的排序思维: 计数排序假定待排序的全部元素都是介于0到K之间的整数.计数排序使用一个额外的数组countArray.当中第i个元素是待排序数组array中值等于i的元素的个数.然后依据数 ...

  3. 排序算法——选择排序(js语言实现)

    选择排序:顾名思义选择,选择排序属于O(N^2)的排序算法,意思就是选择数组中的最小的拿出来放在第一位,然后再剩下的数里面,选择最小的,排在第二位,以此类推. 例如:8  3  4  5  6  2  ...

  4. 希尔排序——C语言

    希尔排序 希尔排序是插入排序的一种,又称“缩小增量排序”,希尔排序是直接插入排序算法的一种更高效的改进版本,关于插入排序可以看下这篇随笔:插入排序——C语言 (图片来源:https://www.cnb ...

  5. 排序(5)---------高速排序(C语言实现)

    继shell发明了shell排序过后呢,各位计算机界的大牛们又開始不爽了,为什么他能发明.我就不能发明呢.于是又有个哥们蹦出来了.哎...那么多排序,就木有一个排序是中国人发明的.顺便吐槽一下,一百年 ...

  6. 排序(4)---------希尔(shell)排序(C语言实现)

    由于考试耽搁了几天,不好意思~~~ 前面的介绍的三种排序算法,都属于简单排序,大家能够看下详细算法,时间复杂度基本都在0(n^2),这样呢,非常多计算机界.数学界的牛人就非常不爽了,他们在家里想啊想, ...

  7. [数据结构] 希尔排序 C语言程序

    //由小到大 //希尔排序 void shellSort( long int array[], int length) { int i; int j; int k; int gap; //gap是分组 ...

  8. 选择排序(直接排序)java语言实现

    class demo { public static void main(String[] args) { int[] arr={1,4,2,6,8,9,0,5,3,2,2,4,4,6,7,8}; f ...

  9. 高速排序java语言实现

    本博客不再更新,很多其它精彩内容请訪问我的独立博客 高速排序是非常重要的排序算法,可是我在学的时候发现网上没有特别好的样例所以自己动手写了一个. 自己动手丰衣足食. package sort; imp ...

  10. 排序(1)---------选择排序(C语言实现)

    选择排序的基本思想: 选择排序(Selection sort)是一种简单直观的排序算法. 它的工作原理例如以下.首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素 ...

随机推荐

  1. printf重定向问题

    1.使用printf库函数时,要加入头文件<stdio.h> 2.另外在keil里面需要把:use MicroLIB 勾选上,不然程序没办法在线调试.编译的时候不会报错. 3.当然可以不用 ...

  2. emmet完整收录(html,css)

    emmet官网 https://emmet.io/ 语法篇 Child: > nav>ul>li <nav> <ul> <li></li&g ...

  3. nvme ioctl解密

    对于Nvme SSD,我们有的时候会用到ioctl系统调用,该调用的流程是怎样的呢? 首先,在注册nvme设备的时候,会初始化该设备的注册了file operations: static const ...

  4. 【Dubbo源码阅读系列】服务暴露之本地暴露

    在上一篇文章中我们介绍 Dubbo 自定义标签解析相关内容,其中我们自定义的 XML 标签 <dubbo:service /> 会被解析为 ServiceBean 对象(传送门:Dubbo ...

  5. jquery中的 append , after , prepend , before 区别

    jQuery append() 方法在被选元素的结尾插入内容. jQuery prepend() 方法在被选元素的开头插入内容. jQuery after() 方法在被选元素之后插入内容. jQuer ...

  6. Elasticsearch 6.3.1、Head插件 安装及配置

    安装Elasticsearch Elasticsearch下载地址:https://www.elastic.co/cn/downloads/elasticsearch 也可以直接使用wget下载到某目 ...

  7. [Doctrine Migrations] 数据库迁移组件的深入解析四:集成diff方式迁移组件

    场景及优势 熟悉Symfony框架之后,深刻感受到框架集成的ORM组件Doctrine2的强大之处,其中附带的数据迁移也十分方便.Doctrine2是使用Doctrine DBAL组件把代码里面的表结 ...

  8. STM32F4XX中断方式通过IO模拟I2C总线Master模式

    STM32的I2C硬核为了规避NXP的知识产权,使得I2C用起来经常出问题,因此ST公司推出了CPAL库,CPAL库在中断方式工作下仅支持无子地址 的器件,无法做到中断方式完成读写大部分I2C器件.同 ...

  9. PE 学习之路 —— 区块表

    1. 前述 在 NT 头结束后,紧接着就是区块表,区块表包含每个块在映象中的信息,分别指向不同的区块实体. 2. 区块表 区块表是一个 IMAGE_SECTION_HEADER 结构数组,这个结构包含 ...

  10. Hadoop生态新增列式存储系统Kudu

        Hadoop生态系统发展到现在,存储层主要由HDFS和HBase两个系统把持着,一直没有太大突破.在追求高吞吐的批处理场景下,我们选用HDFS,在追求低延迟,有随机读写需求的场景下,我们选用H ...