九大排序算法

*    为了实现N个数的排序,将后面N-1个数依次插入到前面已排好的子序列中,

*假定刚开始第1个数是一个已排好序的子序列。经过N-1趟就能得到一个有序序列。

*****时间复杂度:最好情况O(n),最坏情况O(n^2),平均情况O(n^2).

*****空间复杂度:O(1)

*****稳定性:稳定

#include

#include

int main()

{

int n,i,j,temp;

int *p;

scanf("%d",&n);

p=(int *)malloc(sizeof(int)*n);

for(i=0;i

scanf("%d",&p[i]);

}

for(i=1;i

temp=p[i];          //临时存储待排序插入的树

for(j=i;j>0&&p[j-1]>temp;j--)  //每次与前面的书比较至不满足条件或者已经全部比较了才结束

p[j]=p[j-1];

p[j]=temp;

}

for(i=0;i

printf("%d ",p[i]);

}

printf("\n");

return 0;

}

 *<<折半插入排序>>

 

*    与直接插入排序不同的是,折半插入排序不是边比较边移动,而是将比较和移

*动操作分离出来,即先折半查找出元素的待插入位置,然后再统一地移动待插入位

*置之后的所有元素。不难看出折半插入排序仅仅是减少了比较的次数。

*****时间复杂度:O(n^2)

*****空间复杂度:O(1)

*****稳定性:稳定

#include

#include

int main()

{

int i,j,n,temp,low,high,mid;

int *p;

scanf("%d",&n);

p=(int *)malloc(n*sizeof(int));

for(i=0;i

scanf("%d",&p[i]);

}

for(i=1; i

{

temp=p[i];

low=0;

high=i-1;

while(low

{

mid=(low+high)/2;

if(p[i]

high=mid-1;

else

low=mid+1;

}

for(j=i-1;j>=low;j--)    //将该数前面的从low/high开始的数全部后移

p[j+1]=p[j];

p[low]=temp;             //将该数插入

}

for(i=0;i

printf("%d ",p[i]);

printf("\n");

return 0;

}

*<<希尔排序>>

希尔排序的实质就是分组插入排序,该方法又称缩小增量排序,因DL.Shell于1959年提出而得名。

该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)

分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)

时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况)

,效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。

以n=10的一个数组49, 38, 65, 97, 26, 13, 27, 49, 55, 4为例

第一次 gap = 10 / 2 = 5

49   38   65   97   26   13   27   49   55   4

1A                              1B

2A                               2B

3A                              3B

4A                               4B

5A                               5B

1A,1B,2A,2B等为分组标记,数字相同的表示在同一组,大写字母表示是该组的第几个元素,

每次对同一组的数据进行直接插入排序。即分成了五组(49, 13) (38, 27) (65,49) (97,55)

(26, 4)这样每组排序后就变成了(13, 49)  (27, 38)  (49, 65)  (55, 97)  (4, 26),下同。

第二次 gap = 5 / 2 = 2.排序后

13   27   49   55   4    49   38   65   97   26

1A          1B         1C         1D         1E

2A         2B        2C        2D        2E

第三次 gap = 2 / 2 = 1

4   26   13   27   38    49   49   55   97   65

1A  1B   1C   1D   1E    1F   1G   1H   1I   1J

第四次 gap = 1 / 2 = 0 排序完成得到数组:

4   13   26   27   38    49   49   55   65   97

*/

#include

#include

#include

int main(){

int n,i,j,dk,temp;//dk是增量

int *p;

scanf("%d",&n);

p=(int *)malloc(n*sizeof(int));

for(i=0; i

scanf("%d",&p[i]);

for(dk=n/2; dk>0; dk/=2){  // 增量变化

for(i=dk; i

temp = p[i];

for(j=i; j-dk>=0 && p[j-dk]>temp; j-=dk)  //对每个分组进行插入排序

p[j] = p[j-dk];  // 后移

p[j] = temp;

}

for(j=0; j

printf("%d ",p[j]);

printf("\n");

}

return 0;

}

----------------------------------交换排序------------------------------------

*<<冒泡排序>>

*    冒泡排序的基本思想是从后往前(或从前往后)两两比较相邻元素的值,若为

*逆序,则交换它们,直到序列比较完。我们称它为一趟冒泡。每一趟冒泡都会将一

*个元素放置到其最终位置上。

*****时间复杂度:最好情况O(n),最坏情况O(n^2),平均情况O(n^2)

*****空间复杂度:O(1)

*****稳定性:稳定

#include

#include

#include

int main()

{   int n,i,j,temp,swap=0;

int *p;

scanf("%d",&n);

p=(int *)malloc(n*sizeof(int));

for(i=0; i

scanf("%d",&p[i]);

for(i=n-1;i>0;i--){

swap=0;                    //表示序列是否已经有序。若是则不用再继续排序

for(j=0;j

if(p[j]>p[j+1]){

swap=1;

temp=p[j];

p[j]=p[j+1];

p[j+1]=temp;

}

}

for(j=0;j

printf("%d ",p[j]);

printf("\n");

if(swap==0) break;

}

return 0;

}

*<<快速排序>>

时间复杂度为O(nlgn)

//算法1

int quicksort(int *p,int n,int left,int right){

int pivot,temp,i,j;

if(left>=right)

return 0;

i=left;

j=right;

pivot=p[left];

while(i

while(ipivot)

j--;

while(i<=pivot)

i++;

if(i!=j){

temp=p[i];

p[i]=p[j];

p[j]=temp;

}

}

p[left]=p[i];

p[i]=pivot;

quicksort(p,left,i-1);

quicksort(p,i+1,right);

return 0;

}

//算法2

int quicksort(int *p,int left,int right){

int pivot,i,j;

if(left>=right)

return 0;

pivot=p[left];

i=left;

j=right;

while(i

while(ipivot)

j--;

p[i]=p[j];

while(i<=pivot)

i++;

p[j]=p[i];

}

p[i]=pivot;

for(i=0;i

printf("%d ",p[i]);

printf("\n");

quicksort(p,left,i-1);

quicksort(p,i+1,right);

return 0;

}

int main()

{

int n,i;

int *p;

scanf("%d",&n);

p=(int *)malloc(n*sizeof(int));

for(i=0; i

scanf("%d",&p[i]);

quicksort(p,0,n-1);

for(i=0;i

printf("%d ",p[i]);

printf("\n");

return 0;

}

----------------------------------选择排序-------------------------------

*<<简单选择排序>>

 

*    选择排序的算法思想很简单,假设序列为L[n],第i趟排序即从L[i...n]中选择

*关键字最小的元素与L(i)交换,每一趟排序可以确定一个元素的最终位置。经过n-1

*趟排序就可以使得序列有序了。

*****时间复杂度:始终是O(n^2)

*****空间复杂度:O(1)

*****稳定性:不稳定

#include

#include

#include

int main(){

int n,i,j,min,temp;

int *p;

scanf("%d",&n);

p=(int *)malloc(n*sizeof(int));

for(i=0; i

scanf("%d",&p[i]);

for(i=0;i

min=i;       //假设在第i个至后面的所有值中其为最小值

for(j=i+1;j

if(p[j]

min=j;

if(min!=i){    //若实际最小的不是第i个,则交换

temp=p[min];

p[min]=p[i];

p[i]=temp;

}

}

return 0;

}

#include

#include

#include

//调整某个节点并递归调整其调整后可能出现的孩子大于父亲的问题

int adjustheap(int *p,int hn,int i){

int item;

int lchild=2*i+1;

int rchild=2*i+2;

int largest=i;

while(lchild

if(lchildp[largest])   //左孩子存在且大于父亲

largest=lchild;

if(rchildp[largest])   //右孩子存在且大于父亲

largest=rchild;

if(largest!=i){     //若父节点不是三者中最大的

item=p[i];       //将三者中最大的与父节点交换

p[i]=p[largest];

p[largest]=item;

i=largest;       //最大的节点与父节点交换后可能导致以其为父节点的左右孩子比其大。则以其为父节点递归调整

lchild=2*i+1;

rchild=2*i+2;

}

else{

break;

}

}

return 0;

}

//建堆其实就是对无序序列数组对应的完全二叉树的所有节点进行调整形成一个大/小顶堆

int buildheap(int *p,int hn){

int i,begin;

begin=hn/2-1;         //从最后一个节点的父节点开始

for(i=begin;i>=0;i--){

adjustheap(p,hn,i);

}

return 0;

}

int main()

{

int n,i,j,hn,item;

int *p;

scanf("%d",&n);

p=(int *)malloc(n*sizeof(int));

for(i=0; i

scanf("%d",&p[i]);

hn=n;

buildheap(p,hn);  //将无序序列建成堆并调整所有节点使树成为大/小顶堆

while(hn>1){

item=p[0];       //将堆顶与最底一个节点交换

p[0]=p[hn-1];

p[hn-1]=item;

hn--;

adjustheap(p,hn,0);  //将重新形成的无序序列的根节点与左右孩子进行调整

}                    //不用重新调整所有节点,因为最大/小值必定为根节点的左/右孩子

for(j=0;j

printf("%d ",p[j]);

printf("\n");

return 0;

}

-----------------------------------归并排序--------------------------------

*<<归并排序>>

一. 算法描述

合并有序数列的效率是比较高的,完全可以达到O(n)。

归并排序的基本思路就是先将待排序数组分成两组A,B,然后如果这两组组内的数据都是有序的,就可以

利用上面的逻辑(合并有序数列逻辑)很方便的将这两个有序数组数据再进行合并排序。

问题关键是如何让这两组组内数据有序呢?

可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经

达到了有序,然后再合并相邻的两个小组就可以了。

这样通过先递归的分解待排序数列,再合并数列就完成了归并排序的过程。实现归并排序。

二. 算法分析

平均时间复杂度:O(nlog2n)

空间复杂度:O(n)  (用于存储有序子序列合并后有序序列)

稳定性:稳定

*/

//递归算法

#include

#include

#include

int meger(int *p,int low,int high){

int mid=(low+high)/2;

int left1=low;

int right1=mid;

int left2=mid+1;

int right2=high;

int *item,i,k;

item=(int *)malloc((high-low+1)*sizeof(int));//暂存合并后的序列

k=0;

while(left1<=right1&&left2<=right2)

{

if(p[left1]

item[k++]=p[left1++];

else

item[k++]=p[left2++];

}

while(left1<=right1)

item[k++]=p[left1++];

while(left2<=right2)

item[k++]=p[left2++];

for(i=0; i

p[low+i]=item[i];   //对有序的俩段序列进行合并

}

int meger_sort(int *p,int low,int high)

{

int mid;

if(low

{

mid=(low+high)/2;   //递归不断分段,至每段长度都为一时返回

meger_sort(p,low,mid);

meger_sort(p,mid+1,high);

meger(p,low,high);

}

}

int main()

{

int n,i;

int *p;

scanf("%d",&n);

p=(int *)malloc(n*sizeof(int));

for(i=0; i

scanf("%d",&p[i]);

meger_sort(p,0,n-1);

for(i=0; i

printf("%d ",p[i]);

printf("\n");

return 0;

}

//非递归调用

#include

#include

#include

int _sort(int *p,int n,int start1,int start2,int num){

int *item;

item=(int *)malloc(n*sizeof(int));

int i=0,j=0,k=0;

while(i

if(p[start1+i]

item[k++]=p[start1+i];

i++;

}

else if(p[start1+i]==p[start2+i]){

item[k++]=p[start1+i];

i++;

j++;

}

else{

item[k++]=p[start2+j];

j++;

}

}

while(i

item[k++]=p[start1+i];

i++;

}

while(j

item[k++]=p[start2+j];

j++;

}

for(i=start1,j=0;i

p[i]=item[j];

}

int meger_sort(int *p,int n){

int num=1,i,j;

while(num

for(i=0;i

int start=2*num*i;

_sort(p,n,start,start+num,num);

}

num*=2;

}

return 0;

}

int main()

{

int n,i;

int *p;

scanf("%d",&n);

p=(int *)malloc(n*sizeof(int));

for(i=0; i

scanf("%d",&p[i]);

meger_sort(p,n);

for(i=0;i

printf("%d ",p[i]);

printf("\n");

return 0;

}

----------------------------------基数排序---------------------------

*<<基数排序>>

一. 算法描述

基数排序(以整形为例),将整形10进制按每位拆分,然后从低位到高位依次比较各个位。主要分为两个过程:

(1)分配,先从个位开始,根据位值(0-9)分别放到0~9号桶中(比如53,个位为3,则放入3号桶中)

(2)收集,再将放置在0~9号桶中的数据按顺序放到数组中

重复(1)(2)过程,从个位到最高位(比如32位无符号整形最大数4294967296,最高位10位)

二. 算法分析

平均时间复杂度:O(dn)(d即表示整形的最高位数)

空间复杂度:O(10n) (10表示0~9,用于存储临时的序列)

稳定性:稳定

*/

//三. 算法实现

#include

#include

#include

#define MAX 10

//取得一个数第pos位的值

int getnumpos(int num,int pos){

int temp=1,i;

for(i=0;i

temp*=10;

return (num/temp);

}

int radixsort(int *p,int n){

int i,j,k,pos,count,index;

int *q[10];   //指针数组指向0~9号长度均为n的数组,分别存储对应位值的待排序数

for(i=0;i<10;i++){

q[i]=(int *)malloc((n+1)*sizeof(int));

q[i][0]=0;   //0号单元不存待排序数,标示该数组中已存的个数

}

for(pos=1;pos

for(j=0;j

count=getnumpos(p[j],pos);

index=++q[count][0];

q[count][index]=p[j];

}

for(i=0,k=0;i<10;i++){  //收集到原来数组中

for(j=1;j<=q[i][0];j++)

p[k++]=q[i][j];

q[i][0]=0;        //复位

}

}

}

int main()

{

int n,i;

int *p;

scanf("%d",&n);

p=(int *)malloc(n*sizeof(int));

for(i=0; i

scanf("%d",&p[i]);

radixsort(p,n);

for(i=0;i

printf("%d ",p[i]);

printf("\n");

return 0;

}

时间: 2024-10-19 07:22:16

九大排序算法的相关文章

九大排序算法总结

九大排序算法再总结 算法的由来:9世纪波斯数学家提出的:“al-Khowarizmi” 排序的定义: 输入:n个数:a1,a2,a3,...,an 输出:n个数的排列:a1',a2',a3',...,an',使得a1'<=a2'<=a3'<=...<=an'. In-place sort(不占用额外内存或占用常数的内存):插入排序.选择排序.冒泡排序.堆排序.快速排序. Out-place sort:归并排序.计数排序.基数排序.桶排序. 当需要对大量数据进行排序时,In-plac

九大排序算法Java实现

之前学习数据结构与算法时花了三天时间整理九大排序算法,并采用Java语言来实现,今天第一次写博客,刚好可以把这些东西从总结的文档中拿出来与大家分享一下,同时作为自己以后的备忘录. 1.排序算法时间复杂度.稳定性分类: 2.排序算法问题描述与实现 2.1冒泡排序(交换排序-稳定) [问题描述]对于一个int数组,请编写一个冒泡排序算法,对数组元素排序. 问题分析:冒泡排序,顾名思义,从前往后遍历,每次遍历在末尾固定一个最大值. 易错点:每次内层循环结束都会在末尾确定一个元素的位置,因此内层循环的判

九大排序算法及其实现- 插入.冒泡.选择.归并.快速.堆排序.计数.基数.桶排序

  闲着的时候看到一篇“九大排序算法在总结”,瞬间觉得之前数据结构其实都有学过,但当初大多数都只是老师随口带过,并没有仔细研究一下.遂觉:这是欠下的账,现在该还了.   排序按照空间分类: In-place sort不占用额外内存或占用常数的内存 插入排序.选择排序.冒泡排序.堆排序.快速排序. Out-place sort:归并排序.计数排序.基数排序.桶排序. 或者按照稳定性分类: stable sort:插入排序.冒泡排序.归并排序.计数排序.基数排序.桶排序. unstable sort

九大排序算法,你会几个?

概述排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. 当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序.堆排序或归并排序序. 快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短: 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入到已

Javascript九大排序算法详解

排序很多时候都会用到,而在js中排序的算法有九个是人们常用的,而且使用起来可以很流畅.本文将对这九种排序算法进行详细介绍,教程尚硅谷JavaScript DOM视频教程还有详细的代码分享哦. 一.插入排序 1)算法简介 插 入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法.它的工作原理是 通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入.插入排序在实现上,通常采用in-place排序(即只需用到 O(1)的额外空间的排序),因而在从后向前扫

九大排序算法再总结

本文是 http://blog.csdn.net/xiazdong/article/details/7304239 的补充,当年看了<大话数据结构>总结的,但是现在看了<算法导论>,发现以前对排序的理解还不深入,所以打算对各个排序的思想再整理一遍. 本文首先介绍了基于比较模型的排序算法,即最坏复杂度都在Ω(nlgn)的排序算法,接着介绍了一些线性时间排序算法,这些排序算法虽然都在线性时间,但是都是在对输入数组有一定的约束的前提下才行. 这篇文章参看了<算法导论>第2.3

【转】九大排序算法

如果要转载,需要注明出处: http://blog.csdn.net/xiazdong 本文是 http://blog.csdn.net/xiazdong/article/details/7304239 的补充,当年看了<大话数据结构>总结的,但是现在看了<算法导论>,发现以前对排序的理解还不深入,所以打算对各个排序的思想再整理一遍. 本文首先介绍了基于比较模型的排序算法,即最坏复杂度都在Ω(nlgn)的排序算法,接着介绍了一些线性时间排序算法,这些排序算法虽然都在线性时间,但是都

重新回顾九大排序算法

最近无聊想回顾一下大一学过的排序算法.目前才写了一点...心得以后再补充吧!! 1.插入排序 //插入排序 /*  * 把数组a的第n个数插入前n-1个数中,注意前n-1个数已经是排好序的了  * */ public static void insertSort(int[] arr){   int len = arr.length;   int key;   int i,j;   for(i = 1; i < len; i++){    j = i;    key = arr[i];      

【Java】九大排序算法总结(复杂度及应用场景)

1.冒泡排序,不管序列是怎样,都是要比较n(n-1)/2 次的,最好.最坏.平均时间复杂度都为O(n²),需要一个临时变量用来交换数组内数据位置,所以空间复杂度为O(1). 优化:使用一个标志位来判断是否有序,若果有序,那么循环一次就直接退出,时间复杂度为O(n). 2.选择排序是冒泡排序的改进,同样选择排序无论序列是怎样的都是要比较n(n-1)/2次的,最好.最坏.平均时间复杂度也都为O(n²),需要一个临时变量用来交换数组内数据位置,所以空间复杂度为O(1). 3.插入排序,如果序列是完全有

九大排序算法Demo

1. 冒泡排序 冒泡排序(Bubble Sort)是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端. 1 int[] array = {5, 4, 3, 2, 1}; 2 3 boolean isChanged = false; 4 for (int i = 0; i < array.length; i