最近又把排序给复(yu)习(xi)了一遍,在此总结一下~具体理论思想持续补充完善中。。。

1.交换排序

(1)普通冒泡

  • 时间复杂度:最差、平均都是O(n^2),最好是O(n)

  • 空间复杂度:O(1)

      # include<stdio.h>
    
      void bubble(int *list,int len)
    {
    int i,j,t,flag=0;
    for(i=0;i<len-1;i++)
    {
    flag=0;//设置标记,当某一轮交换没有交换任何数,那下一轮交换也不必进行了
    for(j=0;j<len-1-i;j++)
    {
    if(list[j]>list[j+1])
    {
    t=list[j];
    list[j]=list[j+1];
    list[j+1]=t;
    flag=1;
    }
    }
    if(flag==0)
    {
    break;
    }
    } } void main()
    {
    int n,list[10];
    printf("请输入10个整数:");
    for(n=0;n<10;n++)
    {
    scanf("%d",&list[n]);
    }
    printf("\n");
    bubble(list,10);
    for(n=0;n<10;n++)
    {
    printf("%d\t",list[n]);
    }
    printf("\n"); }

(2)鸡尾酒排序:双向冒泡

  • 时间复杂度:最差、平均都是O(n^2),最好是O(n)

  • 空间复杂度:O(1)

      #include<stdio.h>
    
      void CocktailBubble(int *list,int n)
    {
    int low=0,high=n-1,j,t,flag;
    while(low<high)
    {
    flag=0;//一次进行两趟for循环,第一个for循环排最大值(次大值),第二个for循环排最小值(次小值),只要其中一趟没有交换任何数字就可以结束排序
    for(j=low;j<high;j++)
    {
    if(list[j]>list[j+1])
    {
    t=list[j];
    list[j]=list[j+1];
    list[j+1]=t;
    flag=1;
    }
    }
    if(flag==0)
    {
    break;
    }
    high--;//上述for循环第一次结束,排完最大值;第二次,排完次大值
    for(j=high;j>low;j--)
    {
    if(list[j]<list[j-1])
    {
    t=list[j];
    list[j]=list[j-1];
    list[j-1]=t;
    }
    }
    if(flag==0)
    {
    break;
    }
    low++;//上述for循环第一次结束,排完最小值;第二次,排完次小值 }
    } void main(){
    int i,list[10];
    printf("请输入10个整数:");
    for(i=0;i<10;i++){
    scanf("%d",&list[i]);
    }
    for(i=0;i<10;i++){
    printf("%d ",list[i]);
    }
    printf("\n");
    CocktailBubble(list,10);
    for(i=0;i<10;i++){
    printf("%d ",list[i]);
    }
    printf("\n"); while(1){
    ;
    }
    }

(3)快速排序法

  • 时间复杂度:平均O(nlogn),最坏O(n^2)

  • 空间复杂度:O(logn)

      #include<stdio.h>
    #include<stdlib.h>
    int Partition(int *list,int low,int high)//该划分算法的工作为:排好list[low],然后返回list[low]排好后的位置
    {
    int i=low,j=high;
    int t=list[low]; while(i<j)
    {
    while(list[j]>=t&&i<j)
    {
    j--;
    }
    if(i<j)
    {
    list[i]=list[j];
    i++;
    } while(list[i]<=t&&i<j)
    {
    i++;
    }
    if(i<j)
    {
    list[j]=list[i];
    j--;
    } }
    list[i]=t;
    return i;
    } void QuickSort(int *list,int low,int high)
    {
    int p;
    if(low<high)
    {
    p=Partition(list,low,high);//每运行一次,排好list[low],然后返回list[low]值排好后的位置,然后对其左右区间进行递归
    QuickSort(list,low,p-1);
    QuickSort(list,p+1,high);
    }
    } main()
    {
    int list[10],i;
    printf("请输入10个整数:\n");
    for(i=0;i<10;i++)
    {
    scanf("%d",&list[i]);
    } QuickSort(list,0,9); for(i=0;i<10;i++)
    {
    printf("%d\t",list[i]);
    } system("pause");
    }

2.插入排序

(1)直接插入法

时间复杂度:最差、平均都是O(n^2),最好是O(n)

空间复杂度:1

#include<stdio.h>
#include<stdlib.h>
void insertion(int *list,int n)
{
int i,j,t;
for(i=1;i<n;i++)//待插入的是list[1]到list[n-1]
{
if(list[i]<list[i-1])
{
t=list[i];
list[i]=list[i-1];
j=i;
while(t<list[j-1]&&j>=1)
{
list[j]=list[j-1];
j--;
}
list[j]=t;
} }
}
main()
{
int list[10],n=10,i; printf("请输入10个整数:\n");
for(i=0;i<10;i++)
{
scanf("%d",&list[i]);
} insertion(list,10); for(i=0;i<10;i++)
{
printf("%d\t",list[i]);
} system("pause");
}

2)shell排序:分组的插入排序

#include<stdio.h>
#include<stdlib.h> void ShellPass(int *list,int n,int incre)
{
int i,j,t,k;//以第一个步长list[0]……list[incre-1]为基准,待插入的是list[incre]……list[n-1],每个插的时候和自己的增量组比较。 for(i=incre;i<n;i++)
{
if(list[i]<list[i-incre])
{
t=list[i];
list[i]=list[i-incre];
j=i;
while(t<list[j-incre]&&j>=incre)
{
list[j]=list[j-incre];
j-=incre;
}
list[j]=t; }
} }
void ShellSort(int *list,int n)
{
int incre=n;
while(1)
{
incre=incre/3+1;
ShellPass(list,n,incre);
if(incre==1)
{
break;
}
}
} main()
{
int list[10],n=10,i; printf("请输入10个整数:\n");
for(i=0;i<10;i++)
{
scanf("%d",&list[i]);
} ShellSort(list,10); for(i=0;i<10;i++)
{
printf("%d\t",list[i]);
} system("pause");
}

3.选择排序

(1)普通选择排序

时间复杂度:最差、平均都是O(n^2),最好是O(n)

空间复杂度:1

稳定性:不稳定

#include<stdio.h>
void SimpleSort(int *list,int n)
{
int i,j,k,t;
for(i=0;i<n;i++)
{
k=i;
for(j=i+1;j<n;j++)
{
if(list[j]<list[k])
{
k=j;//将比list[k]小的list[j]的j存入k
}
}
if(k!=i)//每进行一次循环找出list[i]到list[n-1]中最小的那个,将这个最小值与list[i]交换位置
{
t=list[i];
list[i]=list[k];
list[k]=t;
}
}
} main()
{
int list[10],n=10,i;
printf("请输入10个整数:\n");
for(i=0;i<10;i++)
{
scanf("%d",&list[i]);
}
SimpleSort(list,10); for(i=0;i<10;i++)
{
printf("%d",list[i]);
}
system("pause");
}

(2) 堆排序

#include<stdio.h>
#include<stdlib.h> //向下调整运算
void AdjustDown(int *h,int i,int n)//待排序数组h[],待调整元素下标号i和序列长度n
{
int l=2*i+1,j;//l为待调整元素左孩子下标
int temp=h[i];//待调整元素
while(l<=n-1)
{
if(l<n-1&&h[l]>h[l+1])
{
l++;//现在l为待调整元素左右孩子中较小孩子的下标
}
if(temp<h[l])
{
break;//当待调整元素小于左右孩子时,直接退出,调整结束
}
h[i]=h[l];//交换h[i]和其较小的孩子,由于h[i]保存在temp中,所以可以直接赋值
i=l;//为下一次调整做好准备
l=l*2+1;
}
h[i]=temp;//填入temp,调整结束 for(j=0;j<10;j++)
{
printf("%d\t",h[j]); }
printf("\n");
} //建立小根堆
void CreatHeap(int *h,int n)
{
int i,j;
for(i=(n-2)/2;i>=0;i--)
{
printf("%d\n",i);//待调整的元素下标为i
AdjustDown(h,i,n);//待调整的元素为下标为n/2到0的元素 }
} //堆排序
void HeapSort(int *h,int n)
{
int temp,i;
CreatHeap(h,n);//得到一个小根堆
for(i=n-1;i>=0;i--)
{
temp=h[i];//首末位交换,将最小值(首位)和末位交换,排好最小值(即排在最后),再将剩余元素(除最后一个元素外)调整为小根堆
h[i]=h[0];
h[0]=temp;
AdjustDown(h,0,i); }
} void main()
{
int i,h[10];
for(i=0;i<10;i++)
{
scanf("%d",&h[i]);
}
HeapSort(h,10);
for(i=0;i<10;i++)
{
printf("%d\t",h[i]);
} system("pause"); }

注意:堆排序所建立的树不能采用链式存储,只能采用顺序存储

4.归并排序

时间复杂度:最差、平均、最好都是O(nlogn)

空间复杂度:O(n)

#include<stdio.h>
#include<stdlib.h>
void Merge(int *list,int *newlist,int s,int m,int t)
{
int i,j,k;
i=s;
j=m+1;
k=s;
while(i<=m&&j<=t)
{
if(list[i]<=list[j])
{
newlist[k]=list[i];
k++;
i++;
}
else
{
newlist[k]=list[j];
k++;
j++;
}
} while(i<=m)//剩余的若是前一个序列,则其直接按并入newlist
{
newlist[k]=list[i];
i++;
k++;
}
while(j<=t)
{
newlist[k]=list[j];
j++;
k++;
}
} void MSort(int *list,int *newlist,int s,int t)
{
int *newlist2;
int m;
newlist2=(int *)malloc((t-s+1)*sizeof(int));//分配一个新数组,和list等长 if(s==t)
{
newlist[s]=list[s];
}
else
{
m=(s+t)/2;
MSort(list,newlist2,s,m);//将list[s]……list[m]递归归并为有序的newlist2[s]……newlist2[m]
MSort(list,newlist2,m+1,t);//将list[m+1]……list[t]递归归并为有序的newlist2[m+1]……newlist2[t]
Merge(newlist2,newlist,s,m,t);//将newlist2[s]……newlist2[m]和newlist2[m+1]……newlist2[t]归并到newlist[s]……newlist[t]
}
}
void MergeSort(int *list,int *newlist,int n)
{
MSort(list,newlist,0,n-1);
}
main()
{
int list[10],n=10,i,newlist[10];
printf("请输入10个整数:\n");
for(i=0;i<10;i++)
{
scanf("%d",&list[i]);
}
MergeSort(list,newlist,10); for(i=0;i<10;i++)
{
printf("%d",newlist[i]);
} system("pause");
}

最后,总结一下各种排序算法时间空间复杂度比较

大类|排序方法|时间复杂度|空间复杂度|稳定性|备注

----|-------|---------|--------|------

交换法|冒泡法|最差、平均都是O(n^2),最好是O(n)|1|稳定|n较小时较好

交换法|鸡尾酒冒泡法|最差、平均都是O(n^2),最好是O(n)|1|稳定|n较小时较好

交换法|快速排序|平均O(nlogn),最坏是O(n^2)|O(logn)|不稳定|n大时较好

插入法|直接插入法|最差、平均都是O(n^2),最好是O(n)|1|稳定|大部分已排序时较好

插入法|希尔排序(分组的插入法)|平均是O(nlogn)|1|不稳定

选择法|普通选择|最差、平均都是O(n^2)|1|不稳定|n较小时较好

选择法|堆排序|最差、平均、最好都是O(nlogn)|1|不稳定|n大时较好

归并排序|归并排序|最差、平均、最好都是O(nlogn)|O(n)|稳定|n大时较好

基数排序|基数排序|O(dn)(d是常数)|O(n)|稳定

常用排序算法总结(C语言描述)的更多相关文章

  1. 常用七大经典排序算法总结(C语言描述)

    简介 其中排序算法总结如下: 一.交换排序 交换排序的基本思想都为通过比较两个数的大小,当满足某些条件时对它进行交换从而达到排序的目的. 1.冒泡排序 基本思想:比较相邻的两个数,如果前者比后者大,则 ...

  2. 几种经典排序算法的R语言描述

    1.数据准备 # 测试数组 vector = c(,,,,,,,,,,,,,,) vector ## [] 2.R语言内置排序函数 在R中和排序相关的函数主要有三个:sort(),rank(),ord ...

  3. 链表插入和删除,判断链表是否为空,求链表长度算法的,链表排序算法演示——C语言描述

    关于数据结构等的学习,以及学习算法的感想感悟,听了郝斌老师的数据结构课程,其中他也提到了学习数据结构的或者算法的一些个人见解,我觉的很好,对我的帮助也是很大,算法本就是令人头疼的问题,因为自己并没有学 ...

  4. 【最全】经典排序算法(C语言)

    算法复杂度比较: 算法分类 一.直接插入排序 一个插入排序是另一种简单排序,它的思路是:每次从未排好的序列中选出第一个元素插入到已排好的序列中. 它的算法步骤可以大致归纳如下: 从未排好的序列中拿出首 ...

  5. 我们一起来排序——使用Java语言优雅地实现常用排序算法

    破阵子·春景 燕子来时新社,梨花落后清明. 池上碧苔三四点,叶底黄鹂一两声.日长飞絮轻. 巧笑同桌伙伴,上学径里逢迎. 疑怪昨宵春梦好,元是今朝Offer拿.笑从双脸生. 排序算法--最基础的算法,互 ...

  6. 常用排序算法的python实现和性能分析

    常用排序算法的python实现和性能分析 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试 ...

  7. Java常用排序算法+程序员必须掌握的8大排序算法+二分法查找法

    Java 常用排序算法/程序员必须掌握的 8大排序算法 本文由网络资料整理转载而来,如有问题,欢迎指正! 分类: 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排 ...

  8. 转载部长一篇大作:常用排序算法之JavaScript实现

    转载部长一篇大作:常用排序算法之JavaScript实现 注:本文是转载实验室同门王部长的大作,找实习找工作在即,本文颇有用处!原文出处:http://www.cnblogs.com/ywang172 ...

  9. Java 常用排序算法/程序员必须掌握的 8大排序算法

    Java 常用排序算法/程序员必须掌握的 8大排序算法 分类: 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排序(直接选择排序.堆排序) 4)归并排序 5)分配 ...

  10. 面试中常用排序算法实现(Java)

    当我们进行数据处理的时候,往往需要对数据进行查找操作,一个有序的数据集往往能够在高效的查找算法下快速得到结果.所以排序的效率就会显的十分重要,本篇我们将着重的介绍几个常见的排序算法,涉及如下内容: 排 ...

随机推荐

  1. This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its 错误解决办法

    This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary log ...

  2. 今天在网上查看了一个socket程序,运行的时候一直报错,经过队友解决?

    1.首先是问题代码ip_port = ('192.168.12.2',8001)2.上边的代码本身没有问题,但是必须经过修改自己本机的局域网IP地址才能顺利链接请参考上一篇blog的地址,查看本机的i ...

  3. 九度OJ 1337:寻找最长合法括号序列 (DP)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:839 解决:179 题目描述: 给你一个长度为N的,由'('和')'组成的括号序列,你能找出这个序列中最长的合法括号子序列么?合法括号序列的 ...

  4. 1.设计模式-------Iterator

    本文主要是参考<图解设计模式>写的读书笔记: 开发中我用到遍历集合时候,无非我常用的就是简单的for循环,foreach,iterator 这三种方式进行遍历! 当然这三种的效率: 学习I ...

  5. PBR探索

    原理 根据能量守恒,以及一系列光照原理得出微表面BRDF(Bidirectional Reflectance Distribution Function)公式 // D(h) F(v,h) G(l,v ...

  6. zip filter map 列表生成器

    map map(function, list): 就是对list 中的每一个元素都调用function函数进行处理,返回一个map的对象 list一下就可以生成一个列表 或者for循环该对象就可以输出 ...

  7. 7 Javascript:表单与验证-非空验证

    表单提交前要检查数据的合法性 在要对表单里的数据进行验证的时候,能够利用getElementById()来訪问网页上不论什么一个元素 每一个表单域都有一个form对象,可被传给不论什么验证表单数据的函 ...

  8. Android Message handling (based on KK4.4)

    一.几个关键概念 1.MessageQueue:是一种数据结构,见名知义,就是一个消息队列.存放消息的地方.每个线程最多仅仅能够拥有一个MessageQueue数据结构. 创建一个线程的时候,并不会自 ...

  9. jQuery:[1]实现图片上传并预览

    jQuery:[1]实现图片上传并预览 原理 预览思路 1.当上传对象的input被触发并选择本地图片之后获取要上传的图片对象的URL: 2.把对象URL赋值给实现写好的img标签的src属性 Fil ...

  10. iOS 发大招 otherButtonTitles:(nullable NSString *)otherButtonTitles, ... 写法 && 编写通用类的时候关于可变参数的处理

    开始 我  以为 这个 alertView 里面 ...的写法  应该 是一个 普通的数组  然 并没有 分享一篇好文 http://www.tekuba.net/program/290/ IOS实现 ...