最近又把排序给复(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. windowsphone8.1学习笔记之Toast通知

    熟悉或者了解wp系统的人都知道wp的Toast,Toast(吐司)通知是在屏幕最顶上弹出来的提示框,它专为与锁屏提醒.磁贴通知和应用中UI结合使用而设计,但它不是MessageDialog.说简单点它 ...

  2. WINDOWS的用户和用户组说明

    1.基本用户组 Administrators 属于该administators本地组内的用户,都具备系统管理员的权限,它们拥有对这台计算机最大的控制权限,可以执行整台计算机的管理任务.内置的系统管理员 ...

  3. Android5.0以后版本把应用移动到SD或者TF卡的方法

    由于手机内存较小,才8G,用的时间一久,内部存储就满了,天天删垃圾,WIFI还老断线,终于忍无可忍了,决定把应用移动到SD卡,实践下来,只有少部分App默认支持移动到SD卡,大部分程序不支持只能装在内 ...

  4. Python菜鸟之路:Python基础-类(1)——概念

    什么是类? 在python中,把具有相同属性和方法的对象归为一个类(class).类是对象的模板或蓝图,类是对象的抽象化,对象是类的实例化.类不代表具体的事物,而对象表示具体的事物. 类的创建 cla ...

  5. windows7下cmd命令窗口没有滚动条的解救方法

    由于昨天的好123问题没有解决,我想查看一下本机的ip地址等,于是打开了cmd窗口,输入ipconfig/all命令进行查看,但是发现出现了下面的窗口,无法进行滚动,完全无法查看详细的信息. 然后我百 ...

  6. 003-unity3d 物理引擎简介以及示例

    一.概述 物理引擎就是模拟真实世界中物体碰撞.跌落等反应的引擎,通过ballence.愤怒的小鸟等理解.Unity3D的物理引擎使用的是Nvidia的PhysX. 物理引擎是一个计算机程序模拟牛顿力学 ...

  7. ARDUINO解析GPS数据,读取出来GPRMC帧数据

    测试板子使用ARDUINO MEGA2560 #include <TimerOne.h> #define GPSSerial Serial1 #define DebugSerial Ser ...

  8. LeeCode:两数之和【1】

    LeeCode:两数之和[1] 题目描述 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 给定 nums = [2 ...

  9. Shiro:学习笔记(2)——授权

    Shiro:学习笔记(2)——授权 Shiro的三种授权方式 编程式: Subject subject = SecurityUtils.getSubject(); if(subject.hasRole ...

  10. 【Flask】ORM模型创建及数据库映射

    1. 用 declarative_base 根据 engine 创建一个ORM基类.2. 用 Base 类作为基类来写自己的ORM类.要定义 __tablename__ 类属性,来指定这个模型映射到数 ...