导航:首页 > 使用方法 > 四种常用数据排序方法

四种常用数据排序方法

发布时间:2022-09-04 02:45:27

Ⅰ 常用的数据排序算法有哪些,各有什么特点举例结合一种排序算法并应用数组进行数据排序。

排序简介
排序是数据处理中经常使用的一种重要运算,在计算机及其应用系统中,花费在排序上的时间在系统运行时间中占有很大比重;并且排序本身对推动算法分析的发展也起很大作用。目前已有上百种排序方法,但尚未有一个最理想的尽如人意的方法,本章介绍常用的如下排序方法,并对它们进行分析和比较。

1、插入排序(直接插入排序、折半插入排序、希尔排序);
2、交换排序(起泡排序、快速排序);
3、选择排序(直接选择排序、堆排序);
4、归并排序;
5、基数排序;

学习重点
1、掌握排序的基本概念和各种排序方法的特点,并能加以灵活应用;
2、掌握插入排序(直接插入排序、折半插入排序、希尔排序)、交换排序(起泡排序、快速排序)、选择排序(直接选择排序、堆排序)、二路归并排序的方法及其性能分析方法
3、了解基数排序方法及其性能分析方法。

排序(sort)或分类

所谓排序,就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来。其确切定义如下:
输入:n个记录R1,R2,…,Rn,其相应的关键字分别为K1,K2,…,Kn。
输出:Ril,Ri2,…,Rin,使得Ki1≤Ki2≤…≤Kin。(或Ki1≥Ki2≥…≥Kin)。

1.被排序对象--文件
被排序的对象--文件由一组记录组成。
记录则由若干个数据项(或域)组成。其中有一项可用来标识一个记录,称为关键字项。该数据项的值称为关键字(Key)。
注意:
在不易产生混淆时,将关键字项简称为关键字。

2.排序运算的依据--关键字
用来作排序运算依据的关键字,可以是数字类型,也可以是字符类型。
关键字的选取应根据问题的要求而定。
【例】在高考成绩统计中将每个考生作为一个记录。每条记录包含准考证号、姓名、各科的分数和总分数等项内容。若要惟一地标识一个考生的记录,则必须用"准考证号"作为关键字。若要按照考生的总分数排名次,则需用"总分数"作为关键字。

排序的稳定性

当待排序记录的关键字均不相同时,排序结果是惟一的,否则排序结果不唯一。
在待排序的文件中,若存在多个关键字相同的记录,经过排序后这些具有相同关键字的记录之间的相对次序保持不变,该排序方法是稳定的;若具有相同关键字的记录之间的相对次序发生变化,则称这种排序方法是不稳定的。
注意:
排序算法的稳定性是针对所有输入实例而言的。即在所有可能的输入实例中,只要有一个实例使得算法不满足稳定性要求,则该排序算法就是不稳定的。

排序方法的分类

1.按是否涉及数据的内、外存交换分
在排序过程中,若整个文件都是放在内存中处理,排序时不涉及数据的内、外存交换,则称之为内部排序(简称内排序);反之,若排序过程中要进行数据的内、外存交换,则称之为外部排序。
注意:
① 内排序适用于记录个数不很多的小文件
② 外排序则适用于记录个数太多,不能一次将其全部记录放人内存的大文件。

2.按策略划分内部排序方法
可以分为五类:插入排序、选择排序、交换排序、归并排序和分配排序。

排序算法分析

1.排序算法的基本操作
大多数排序算法都有两个基本的操作:
(1) 比较两个关键字的大小;
(2) 改变指向记录的指针或移动记录本身。
注意:
第(2)种基本操作的实现依赖于待排序记录的存储方式。

2.待排文件的常用存储方式
(1) 以顺序表(或直接用向量)作为存储结构
排序过程:对记录本身进行物理重排(即通过关键字之间的比较判定,将记录移到合适的位置)

(2) 以链表作为存储结构
排序过程:无须移动记录,仅需修改指针。通常将这类排序称为链表(或链式)排序;

(3) 用顺序的方式存储待排序的记录,但同时建立一个辅助表(如包括关键字和指向记录位置的指针组成的索引表)
排序过程:只需对辅助表的表目进行物理重排(即只移动辅助表的表目,而不移动记录本身)。适用于难于在链表上实现,仍需避免排序过程中移动记录的排序方法。

3.排序算法性能评价
(1) 评价排序算法好坏的标准
评价排序算法好坏的标准主要有两条:
① 执行时间和所需的辅助空间
② 算法本身的复杂程度

(2) 排序算法的空间复杂度
若排序算法所需的辅助空间并不依赖于问题的规模n,即辅助空间是O(1),则称之为就地排序(In-PlaceSou)。
非就地排序一般要求的辅助空间为O(n)。

(3) 排序算法的时间开销
大多数排序算法的时间开销主要是关键字之间的比较和记录的移动。有的排序算法其执行时间不仅依赖于问题的规模,还取决于输入实例中数据的状态。

文件的顺序存储结构表示

#define n l00 //假设的文件长度,即待排序的记录数目
typedef int KeyType; //假设的关键字类型
typedef struct{ //记录类型
KeyType key; //关键字项
InfoType otherinfo;//其它数据项,类型InfoType依赖于具体应用而定义
}RecType;
typedef RecType SeqList[n+1];//SeqList为顺序表类型,表中第0个单元一般用作哨兵
注意:
若关键字类型没有比较算符,则可事先定义宏或函数来表示比较运算。
【例】关键字为字符串时,可定义宏"#define LT(a,b)(Stromp((a),(b))<0)"。那么算法中"a<b"可用"LT(a,b)"取代。若使用C++,则定义重载的算符"<"更为方便。

按平均时间将排序分为四类:

(1)平方阶(O(n2))排序
一般称为简单排序,例如直接插入、直接选择和冒泡排序;

(2)线性对数阶(O(nlgn))排序
如快速、堆和归并排序;

(3)O(n1+£)阶排序
£是介于0和1之间的常数,即0<£<1,如希尔排序;

(4)线性阶(O(n))排序
如桶、箱和基数排序。

各种排序方法比较

简单排序中直接插入最好,快速排序最快,当文件为正序时,直接插入和冒泡均最佳。

影响排序效果的因素

因为不同的排序方法适应不同的应用环境和要求,所以选择合适的排序方法应综合考虑下列因素:
①待排序的记录数目n;
②记录的大小(规模);
③关键字的结构及其初始状态;
④对稳定性的要求;
⑤语言工具的条件;
⑥存储结构;
⑦时间和辅助空间复杂度等。

不同条件下,排序方法的选择

(1)若n较小(如n≤50),可采用直接插入或直接选择排序。
当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接插人,应选直接选择排序为宜。
(2)若文件初始状态基本有序(指正序),则应选用直接插人、冒泡或随机的快速排序为宜;
(3)若n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序、堆排序或归并排序。
快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;
堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况。这两种排序都是不稳定的。
若要求排序稳定,则可选用归并排序。但本章介绍的从单个记录起进行两两归并的 排序算法并不值得提倡,通常可以将它和直接插入排序结合在一起使用。先利用直接插入排序求得较长的有序子文件,然后再两两归并之。因为直接插入排序是稳定的,所以改进后的归并排序仍是稳定的。

4)在基于比较的排序方法中,每次比较两个关键字的大小之后,仅仅出现两种可能的转移,因此可以用一棵二叉树来描述比较判定过程。
当文件的n个关键字随机分布时,任何借助于"比较"的排序算法,至少需要O(nlgn)的时间。
箱排序和基数排序只需一步就会引起m种可能的转移,即把一个记录装入m个箱子之一,因此在一般情况下,箱排序和基数排序可能在O(n)时间内完成对n个记录的排序。但是,箱排序和基数排序只适用于像字符串和整数这类有明显结构特征的关键字,而当关键字的取值范围属于某个无穷集合(例如实数型关键字)时,无法使用箱排序和基数排序,这时只有借助于"比较"的方法来排序。
若n很大,记录的关键字位数较少且可以分解时,采用基数排序较好。虽然桶排序对关键字的结构无要求,但它也只有在关键字是随机分布时才能使平均时间达到线性阶,否则为平方阶。同时要注意,箱、桶、基数这三种分配排序均假定了关键字若为数字时,则其值均是非负的,否则将其映射到箱(桶)号时,又要增加相应的时间。
(5)有的语言(如Fortran,Cobol或Basic等)没有提供指针及递归,导致实现归并、快速(它们用递归实现较简单)和基数(使用了指针)等排序算法变得复杂。此时可考虑用其它排序。
(6)本章给出的排序算法,输人数据均是存储在一个向量中。当记录的规模较大时,为避免耗费大量的时间去移动记录,可以用链表作为存储结构。譬如插入排序、归并排序、基数排序都易于在链表上实现,使之减少记录的移动次数。但有的排序方法,如快速排序和堆排序,在链表上却难于实现,在这种情况下,可以提取关键字建立索引表,然后对索引表进行排序。然而更为简单的方法是:引人一个整型向量t作为辅助表,排序前令t[i]=i(0≤i<n),若排序算法中要求交换R[i]和R[j],则只需交换t[i]和t[j]即可;排序结束后,向量t就指示了记录之间的顺序关系:
R[t[0]].key≤R[t[1]].key≤…≤R[t[n-1]].key
若要求最终结果是:
R[0].key≤R[1].key≤…≤R[n-1].key
则可以在排序结束后,再按辅助表所规定的次序重排各记录,完成这种重排的时间是O(n)。

Ⅱ 谁教我:数据结构的各种排序

1.快速排序

#include"stdio.h"
#define N 100
int a[N]={0};//存放要排序的数

int Qsort(int m,int n)//对数组中m到n的元素进行快速排序
{
int p,q;
int head,sign;
if(m!=n)//选定的数列不止一个元素
{
head=a[n];//选择数列的末尾元素作为比较元素
p=m;//p标记数列的首元素
q=n-1;//标记末尾元素的前一个元素
sign=n;//记录比较元素的位置,以其作为空位置
while(p<=q)//分别比较p、q所标记的元素与比较元素的大小,比其小的放在左边,比其大的放在右边
{
while(a[p]<head)//p所指元素比比较元素小,p右移
{
p++;
if(p>q)
{
break;
}
}
a[sign]=a[p];//将p所指元素移入空位置
sign=p;//记录空余位置
p++;
if(p>q)
{
break;
}
while(a[q]>head)//q所指元素比比较元素大,q左移
{
q--;
if(p>q)
{
break;
}
}
a[sign]=a[q];
sign=q;
q--;
}
a[sign]=head;//比较完成后,将比较元素移入空位置
if(sign-1>m)
{
Qsort(m,sign-1);//对m到sign-1的数列进行排序
}
if(sign+1<n)
{
Qsort(sign+1,n);//对sign+1到n的数列进行排序
}
}
return(1);
}

int Print(int m,int n)//对m到n的数组序列输出
{
int i;
for(i=m;i<=n;i++)
{
printf("%d\n",a[i]);
}
return(1);
}

int main()
{
int n,i;
scanf("%d",&n);//输入将要排序的数的个数
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);//输入要排序的数
}
Qsort(0,n-1);
Print(0,n-1);
}
二、 详细设计:重要函数中的算法设计,实现流程,传递参数的说明;

三、调试分析与心得体会:
快速排序的思想时从数组序列中选定一个元素,将序列中其余元素与其进行比较,将比其小的放在左边,比其大的放在右边,然后以比较元素为中点,将序列分成两部分,再将它们分别进行快速排序,依次类推,直到序列中只有一个元素为止。

2.合并排序

#include"stdio.h"
#define N 10000
int a[N];//用a数组记录所给无序数列
int b[N]={0};//用b数组记录每次排序之后的a数组
int sign=0;
void Merge(int m,int mid,int n)//将两个有序数列合并成为一个有序数列
{
int i,j,k;
i=k=m;
j=mid+1;
while(i<=mid&&j<=n)//依次比较两个有序数列中的元素,从大到小将其放入b数组相应位置中
{
if(a[i]<a[j])
{
b[k]=a[i];
k++;
i++;
}
else
{
b[k]=a[j];
k++;
j++;
}
}
if(i<=mid)//将比较之后的剩余元素放入b数组相应位置
{
while(i<=mid)
{
b[k]=a[i];
k++;
i++;
}
}
else
{
while(j<=n)
{
b[k]=a[j];
k++;
j++;
}
}
for(i=m;i<=n;i++)//将合并后的数列重新放入a数组相应位置
{
a[i]=b[i];
}
}
int Msort(int m,int n)//对所给无序数列进行排序
{
int mid;
if(n!=m)
{
mid=(n+m)/2; //将数列一分为二直到其只有一个元素
Msort(m,mid);
Msort(mid+1,n);
Merge(m,mid,n);//将分割后的数列重新合并起来
}
return(1);
}
void Print(int num)//将序列依次输出
{
int i;
for(i=0;i<num;i++)
{
printf("%d\n",a[i]);
}
}
int main()
{
int sign;
int i;
int num;
scanf("%d",&num);//输入将要排序的数的个数
for(i=0;i<num;i++)
{
scanf("%d",&a[i]);//依次输入要排序的数
}
sign=Msort(0,num-1);
Print(num);//输出完成排序后的有序数列
}
二、 详细设计:重要函数中的算法设计,实现流程,传递参数的说明;
三、调试分析与心得体会:
合并排序是排序的一种常用方法,其主要思想为:将一个无序数列依次分割直到其每个序列只有一个元素为止,然后再将两个序列合并为一个有序数列,依此类推。

3.我的数据结构实验课题(关于排序)

//问题描述:排序器
//要 求:实现以下六种排序算法,将给定的不同规模大小的数据文件(data01.txt,data02.txt,data03.txt,data04.txt)进行排序,
//并将排序结果分别存储到sorted01.txt,sorted02.txt,sorted03.txt和sorted04.txt文件中。
//1)、Shell排序; 2)、Quick排序
//3)、锦标赛排序; 4)、堆排序
//5)、归并排序; 6)、基数排序
//在实现排序算法1)~4)时,统计数据元素比较的次数和交换的次数,进而对这四种算法在特定数据条件下的效率进行分析和评判。

#include"stdio.h"
#include"math.h"
#include"stdlib.h"
#include"malloc.h"
#define Maxsize 10000000
#define N 20
#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)<(b))
#define LQ(a,b) ((a)<=(b))
#define LEN sizeof(SqList)
#define Maxr 10
#define MAXNUM 100000000

typedef struct node{
int key;
int num;
};
typedef struct {
struct node r[Maxsize+1];
long length;
}SqList,*qSqList;
typedef struct node2{
struct node r;
struct node2 *next;
}RecType;
long shifttimes;//统计移动次数
long comparetimes;//统计比较次数

qSqList creat(char filename[])//读入文件并且将数据保存
{
FILE *fp;
long i;
qSqList L;
L=(qSqList)malloc(LEN);
L->length=0;
if((fp=fopen(filename,"r"))==NULL)//文件不存在时终止程序
{
printf("cannot open file\n");
exit(0);
}
for(i=1;i<Maxsize+1;i++)
{
fscanf(fp,"%ld (%d)",&(L->r[i].key),&(L->r[i].num));
if(L->r[i].key<0)
break;
L->length++;//记录读入的数据长度
}
fclose(fp);
return(L);
}

void Print2(qSqList L)//将序列输出到指定的文件中
{
long i;
FILE *fp;
char filename[N];
printf("\n\t请输入存储文件名:");
scanf("%s",filename);//输入将要储存的文件名
fp=fopen(filename,"w");
for(i=1;i<=L->length;i++)//将链表中数据逐一写入文件中
{
fprintf(fp,"%d (%d)\n",L->r[i].key,L->r[i].num);
}
fclose(fp);
}

void Print(qSqList L)//打印数据个数以及排序过程中的比较次数和移动次数
{
printf("\n\t数据个数:%ld",L->length);
printf("\n\t比较次数:%ld",comparetimes);
printf("\n\t移动次数:%ld",shifttimes);
}

struct node Min1(struct node a,struct node b)//比较两接点关键字的大小
{
struct node temp;
if(a.key>b.key)
temp=b;
else
temp=a;
comparetimes++;
return(temp);
}

qSqList shellinsert(qSqList L,int dk)//对顺序表以dk为增量作直接插入排序
{
int i,j;
for(i=dk+1;i<=L->length;i++)
{
if(LT(L->r[i].key,L->r[i-dk].key))//将L->r[i]插入到有序增量子表
{
L->r[0]=L->r[i];//将L->r[i]暂时存储在L->r[0]
shifttimes++;
for(j=i-dk;j>0&<(L->r[0].key,L->r[j].key);j-=dk)//记录后移,查找插入位置
{
L->r[j+dk]=L->r[j];
comparetimes++;
shifttimes++;
}
if(j>0)
comparetimes++;
L->r[j+dk]=L->r[0];//插入
shifttimes++;
}
comparetimes++;
}
// Print(L);
return(L);
}

qSqList shell(qSqList L)//希尔排序
{
int i,t=0;
int k;
for(t=0;LQ(pow(2,t),(L->length+1));t++);
t=t-1;
// printf("%d",t);
for(i=1;i<=t;++i)
{
k=(int)pow(2,t-i+1)-1;//计算排序增量
L=shellinsert(L,k);
}
Print(L);
Print2(L);
return(L);
}

long Quicksort(qSqList L,long low,long high)//交换顺序表L中子表L->r[low..high]的记录,使枢轴记录到位,并返回其所在位置
{
int pivotkey;
pivotkey=L->r[low].key;//用序列的第一个记录作枢轴记录
while(low<high)//从表的两端交替地向中间扫描
{
while(low<high&&L->r[high].key>=pivotkey)//将比枢轴记录小的记录交换到低端
{
comparetimes++;
high--;
}
comparetimes++;
L->r[0]=L->r[low];
shifttimes++;
L->r[low]=L->r[high];
shifttimes++;
L->r[high]=L->r[0];
shifttimes++;
while(low<high&&L->r[low].key<=pivotkey)//将比枢轴记录大的记录交换到高端
{
comparetimes++;
low++;
}
comparetimes++;
L->r[0]=L->r[low];
shifttimes++;
L->r[low]=L->r[high];
shifttimes++;
L->r[high]=L->r[0];
shifttimes++;
}
return(low);//返回枢轴所在位置
}

qSqList Quick2(qSqList L,long low,long high)//对顺序表L中的子序列L.r[low..high]作快速排序
{
long pivot;
if(low<high)//序列长度大于1
{
pivot=Quicksort(L,low,high);//将序列一分为二
Quick2(L,low,pivot-1);//对低位子表递归排序
Quick2(L,pivot+1,high);//对高位子表递归排序
}
return(L);
}

qSqList Quick(qSqList L)//对顺序表作快速排序
{
long low,high;
low=1;//将第一个数据所在位置定义为低位
high=L->length;//将最后一个数据所在位置定义为高位
L=Quick2(L,low,high);//对顺序表作快速排序
Print(L);
Print2(L);
return(L);
}

void TourSort(SqList *L,long n)//锦标赛排序
{
qSqList Lp;
long i=0,t=1,k=1,w;
while(t<n)//t表示完全二叉树的结点个数
{
t=(long)pow(2,i);
i++;
}
t=2*t;
Lp=(qSqList)malloc((sizeof(SqList)));
Lp->length=t-1;
for(i=t-1;i>=t/2;i--)
{
if(k>n)
Lp->r[i].key=MAXNUM;
else
{
Lp->r[i]=L->r[k];

}
shifttimes++;
k++;
}
i=t-1;
while(i!=1)
{
Lp->r[i/2]=Min1(Lp->r[i],Lp->r[i-1]);
i-=2;
comparetimes++;
shifttimes++;
}
for(i=1;i<=n;i++)
{
L->r[i]=Lp->r[1];
shifttimes++;
w=1;
while(w<t/2)
{
if(Lp->r[2*w].key==Lp->r[w].key)
w*=2;
else
w=2*w+1;
}
Lp->r[w].key=MAXNUM;//将其赋为最大值
shifttimes++;
if(w%2)
Lp->r[w/2]=Lp->r[w-1];
else
Lp->r[w/2]=Lp->r[w+1];
shifttimes++;
while(w!=1)
{
if(w%2)
Lp->r[w/2]=Min1(Lp->r[w],Lp->r[w-1]);
else
Lp->r[w/2]=Min1(Lp->r[w],Lp->r[w+1]);
comparetimes++;
shifttimes++;
w/=2;
}
}
Print(L);
Print2(L);
}

void Heapadjust(qSqList L,long s,long m)//调整L->[s]的关键字,使L->r[s..m]成为一个大顶堆
{
long j;
struct node rc;
rc=L->r[s];
for(j=2*s;j<=m;j*=2)//沿key较大的接点向下筛选
{
if(j<m&<(L->r[j].key,L->r[j+1].key))//j为key较大的记录的下标
{
j++;
comparetimes++;
}
if(!LT(rc.key,L->r[j].key))
{
comparetimes++;
break;
}
L->r[s]=L->r[j];//rc插入位置s
shifttimes++;
s=j;
}
L->r[s]=rc;//插入
shifttimes++;
}

qSqList Heap(qSqList L)//堆排序
{
long i;
for(i=L->length/2;i>0;--i)//把L建成大顶堆
Heapadjust(L,i,L->length);
for(i=L->length;i>1;--i)//将堆顶记录和当前未经排序子序列中最后一个记录交换
{
L->r[0]=L->r[1];
L->r[1]=L->r[i];
L->r[i]=L->r[0];
shifttimes=shifttimes+3;
Heapadjust(L,1,i-1);//将L重新调整为大顶堆
}
Print(L);
Print2(L);
return(L);
}

void Merge(qSqList L,int low,int m,int high)//将两个有序表R[low..m]he R[m+1..high]归并为一个有序表R[low,high]
{
int i=low,j=m+1,k=0;//k是temp的下标,i,j分别为第1,2段的下标
struct node *temp;
temp=(struct node*)malloc((high-low+1)*sizeof(struct node));//用于临时保存有序序列
while(i<=m&&j<=high)//在第1段和第2段均未扫描完时循环
{
if(LT(L->r[j].key,L->r[i].key))//将第1段中的记录放入temp中
{
temp[k]=L->r[j];
j++;
k++;
}
else//将第2段中的记录放入temp中
{
temp[k]=L->r[i];
k++;
i++;
}
}
while(i<=m)//将第1段余下的部分复制到temp
{
temp[k]=L->r[i];
k++;
i++;
}
while(j<=high)//将第2段余下的部分复制到temp
{
temp[k]=L->r[j];
k++;
j++;
}
for(k=0,i=low;i<=high;i++,k++)//将temp复制回L中
{
L->r[i]=temp[k];
}
}

void MSort(qSqList L,int low,int high)//二路归并排序
{
int m;
if (low<high)
{
m=(low+high)/2;
MSort(L,low,m);
MSort(L,m+1,high);
Merge(L,low,m,high);
}
}

void Merging(qSqList L)//归并排序
{
MSort(L,1,L->length);
Print2(L);
}

void Radixsort(qSqList L)//基数排序
{
int g,i,j,k,d=2;
struct node2 *p,*s,*t,*head[10],*tail[10];//定义各链队的首尾指针
for(i=1;i<=L->length;i++) //建立链表
{
s = (struct node2*)malloc(sizeof(struct node2));
s->r.key = L->r[i].key;
s->r.num= L->r[i].num;
if(i==1)
{
t = s;
p = s;
g++;}
else
{
t->next = s;
t = s;
g++;
}
t->next = NULL;
}
d=1;
for(i=1;i<6;i++)
{
for(j=0;j<10;j++)
{head[j] = tail[j] = NULL;} //初始化各链队首、尾指针
while(p!=NULL)//对于原链表中的每个结点循环
{
k = p->r.key/d;
k = k%10;
if(head[k]==NULL)//进行分配
{
head[k]=p;
tail[k]=p;
}
else
{
tail[k]->next=p;
tail[k]=p;
}
p = p->next;//取下一个待排序的元素
}
p=NULL;
for(j=0;j<10;j++)//对每一个链队循环
{
if(head[j]!=NULL)//进行搜集
{
if(p == NULL)
{
p = head[j];
t = tail[j];
}
else
{
t->next=head[j];
t = tail[j];
}
}
}
t->next=NULL;//最后一个结点的next置为空
d=d*10;
}
i=1;
while(p!=NULL)
{
L->r[i] = p->r;
i++;
p=p->next;}
Print2(L);
}

char chmenu()//对排序方法进行选择
{
char ch;
printf("\n\t请选择排序方法:"
"\n\t*************"
"\n\t1.Shell排序"
"\n\t2.Quick排序"
"\n\t3.锦标赛排序"
"\n\t4.堆排序"
"\n\t5.归并排序"
"\n\t6.基排序"
"\n\t7.结束"
"\n\t*************");
do{
printf("\n\tplease choose (1-7):");
getchar();
ch=getchar();
}while(!(ch>'0'&&ch<'8'));
return(ch);
}

void main()
{
int a=1;
FILE *fp;
char ch,filename[N];
qSqList L;
while(a)
{
printf("\n\t请输入读入文件名:");//输入要读入的文件名
scanf("%s",filename);
if((fp=fopen(filename,"r"))==NULL)
{
printf("cannot open the file\n");
exit(0);
}
L=creat(filename);
while(1)
{
if((ch=chmenu())=='7')
break;
switch(ch)
{
case'1':{shifttimes=comparetimes=0;shell(L);}break;
case'2':{shifttimes=comparetimes=0;Quick(L);}break;
case'3':{shifttimes=comparetimes=0;TourSort(L,L->length);}break;
case'4':{shifttimes=comparetimes=0;Heap(L);}break;
case'5':{shifttimes=comparetimes=0;Merging(L);}break;
case'6':{shifttimes=comparetimes=0;Radixsort(L);}break;
}
}
printf("\n\t***************"
"\n\t1.继续读入文件"
"\n\t0.结束"
"\n\t***************");
do{
printf("\n\tplease choose (0-1):");
getchar();
scanf("%d",&a);
}while(!(a==1||a==0));

}
}

Ⅲ 数组的几种排序算法的实现

JAVA中在运用数组进行排序功能时,一般有四种方法:快速排序法、冒泡法、选择排序法、插入排序法。
快速排序法主要是运用了Arrays中的一个方法Arrays.sort()实现。
冒泡法是运用遍历数组进行比较,通过不断的比较将最小值或者最大值一个一个的遍历出来。
选择排序法是将数组的第一个数据作为最大或者最小的值,然后通过比较循环,输出有序的数组。
插入排序是选择一个数组中的数据,通过不断的插入比较最后进行排序。下面我就将他们的实现方法一一详解供大家参考。
<1>利用Arrays带有的排序方法快速排序

public class Test2{ public static void main(String[] args){ int[] a={5,4,2,4,9,1}; Arrays.sort(a); //进行排序 for(int i: a){ System.out.print(i); } } }

<2>冒泡排序算法

public static int[] bubbleSort(int[] args){//冒泡排序算法 for(int i=0;i<args.length-1;i++){ for(int j=i+1;j<args.length;j++){ if (args[i]>args[j]){ int temp=args[i]; args[i]=args[j]; args[j]=temp; } } } return args; }

<3>选择排序算法

public static int[] selectSort(int[] args){//选择排序算法 for (int i=0;i<args.length-1 ;i++ ){ int min=i; for (int j=i+1;j<args.length ;j++ ){ if (args[min]>args[j]){ min=j; } } if (min!=i){ int temp=args[i]; args[i]=args[min]; args[min]=temp; } } return args; }

<4>插入排序算法

public static int[] insertSort(int[] args){//插入排序算法 for(int i=1;i<args.length;i++){ for(int j=i;j>0;j--){ if (args[j]<args[j-1]){ int temp=args[j-1]; args[j-1]=args[j]; args[j]=temp; }else break; } } return args; }

Ⅳ 数据排序的一般方法有什么

数据排序方法
好的排序方法可以有效提高排序速度,提高排序效果。
在计算机领域主要使用数据排序方法根据占用内存的方式不同分为2大类:内部排序方法与外部排序方法。
内部排序方法
若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序。
内排序的方法有许多种,按所用策略不同,可归纳为五类:插入排序、选择排序、交换排序、归并排序和基数排序。
其中,插入排序主要包括直接插入排序和希尔排序两种;选择排序主要包括直接选择排序和堆排序;交换排序主要包括气(冒)泡排序和快速排序。
外部排序方法
外部排序基本上由两个相互独立的阶段组成。首先,按可用内存大小,将外存上含n个记录的文件分成若干长度为k的子文件或段(segment),依次读入内存并利用有效的内部排序方法对它们进行排序,并将排序后得到的有序子文件重新写入外存。通常称这些有序子文件为归并段或顺串;然后,对这些归并段进行逐趟归并,使归并段(有序子文件)逐渐由小到大,直至得到整个有序文件为止。

Ⅳ JAVA中有哪几种常用的排序方法

最主要的是冒泡排序、选择排序、插入排序以及快速排序

1、冒泡排序



冒泡排序是一个比较简单的排序方法。在待排序的数列基本有序的情况下排序速度较快。若要排序的数有n个,则需要n-1轮排序,第j轮排序中,从第一个数开始,相邻两数比较,若不符合所要求的顺序,则交换两者的位置;直到第n+1-j个数为止,第一个数与第二个数比较,第二个数与第三个数比较,......,第n-j个与第n+1-j个比较,共比较n-1次。此时第n+1-j个位置上的数已经按要求排好,所以不参加以后的比较和交换操作。

例如:第一轮排序:第一个数与第二个数进行比较,若不符合要求的顺序,则交换两者的位置,否则继续进行二个数与第三个数比较......。直到完成第n-1个数与第n个数的比较。此时第n个位置上的数已经按要求排好,它不参与以后的比较和交换操作;第二轮排序:第一个数与第二个数进行比较,......直到完成第n-2个数与第n-1个数的比较;......第n-1轮排序:第一个数与第二个数进行比较,若符合所要求的顺序,则结束冒泡法排序;若不符合要求的顺序,则交换两者的位置,然后结束冒泡法排序。


共n-1轮排序处理,第j轮进行n-j次比较和至多n-j次交换。


从以上排序过程可以看出,较大的数像气泡一样向上冒,而较小的数往下沉,故称冒泡法。



public void bubbleSort(int a[])


{


int n = a.length;


for(int i=0;i<n-1;i++)


{


for(int j=0;j<n-i-1;j++)


{


if(a[j] > a[j+1])


{


int temp = a[j];


a[j] = a[j + 1];


a[j + 1] = temp;


}


}


}


}



2、选择排序



选择法的原理是先将第一个数与后面的每一个数依次比较,不断将将小的赋给第一个数,从而找出最小的,然后第二个数与后面的每一个数依次比较,从而找出第二小的,然后第三个数与后面的每一个数依次比较,从而找出第三小的.....直到找到最后一个数。


public void sort(int x[])


{


int n=x.length;


int k,t;


for(int i=0;i<n-1;i++)


{


k=i;


for(int j=i+1;j=n;j++)


{


if(x[j]>x[k])k=j;


if(k!=i)


{


t=x[i];


x[i]=x[k];


x[k]=t;


}


}


}


}


3、插入排序



插入排序的原理是对数组中的第i个元素,认为它前面的i-1个已经排序好,然后将它插入到前面的i-1个元素中。插入排序对少量元素的排序较为有效.



public void sort(int obj[])


{


for(int j=1;j<obj.length;j++)


{


int key=obj[j];


int i=j-1;


while(i>=0&&obj[i]>key)


{


obj[i+1]=obj[i];


i--;


}


obj[i+1]=key;


}


}



4、快速排序



快速排序是对冒泡排序的一种改进。它的基本思想是:通过一次排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按次方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此大道整个数据变成有序序列。



public void quickSort(int obj[],int low,int high)


{


int i=low;


int j=high;


int keyValue=obj[i];


while(i<j)


{


int temp=0;


while(i<j&&obj[j]>=keyValue)


{


j=j-1;


}


temp=obj[j];


obj[j]=obj[i];


obj[i]=temp;


while(i<j&&obj[i]<=keyValue)


{


i=i+1;


}


temp=obj[j];


obj[j]=ojb[i];


obj[i]=temp;


}


obj[i]=keyValue;


if(low<i-1)


{


quickSort(obj,low,i-1);


}


if(high>i+1)


{


quickSort(obj,i+1,high);


}


}

Ⅵ 数据结构中排序方法有多少种

1、插入排序(直接插入排序和希尔排序)
2、选择排序(直接选择排序和堆排序)
3、交换排序(冒泡排序和快速排序)
4、归并排序
5、基数排序
直接插入排序:逐个将后一个数加到前面的排好的序中。在直接插入排序过程中,对其中一个记录的插入排序称为一次排序;直接插入排序是从第二个记录开始进行的,因此,长度为n的记录序列需要进行n-1次排序才能完成整个序列的排序。时间复杂度为O(n2)。
希尔排序:希尔排序又称缩小增量排序,增量di可以有各种不同的取法,但最后一次排序时的增量必须为1,最简单可取di+1=di/2(取小)。时间复杂度为O(n(log2n)2)。
直接选择排序
说明:每次将后面的最小的找出来插入前面的已排好的序中。同理,具有n个记录的序列要做n-1次排序。
时间复杂度为O(n2)。
冒泡排序:两个两个比较,将大的往后移。通过第一次冒泡排序,使得待排序的n个记录中关键字最大的记录排到了序列的最后一个位置上。然后对序列中前n-1个记录进行第二次冒泡排序。。。对于n个记录的序列,共需进行n次冒泡排序。时间复杂度为O(n2)。
快速排序:又叫分区交换排序,是对冒泡排序方法的一种改进。时间复杂度为O(nlog2n)。
归并排序:将两个或两个以上的有序数据序列合并成一个有序数据序列的过程。时间复杂度为O(nlog2n)。

Ⅶ 排序有几种方法

一. 冒泡排序

冒泡排序是是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把它们交换过来。遍历数列的工作是重复的进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端

1.冒泡排序算法的运作如下:
(1)比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个
(2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素还是最大的数
(3)针对所有的元素重复以上的步骤,除了最后一个
二. 选择排序
选择排序是一种简单直观的排序算法。他的工作原理如下:
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置(末尾位置),然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕
选择排序的主要优点与数据移动有关。如果某个元素位于正确的最终位置上,则它不会被移动。选择排序每次交换一对元素,他们当中至少有一个将被移到最终位置上,因此对n个元素的表进行排序总共进行至多n-1次交换。在所有的完全依靠交换去移动 元素的排序方法中,选择排序属于非常好的一种
三. 插入排序

插入排序是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在从后向前扫描的过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间
四. 快速排序
快速排序,又称划分交换排序。通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都要小,然后再按此方法对两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
五 希尔排序过程

希尔排序是插入排序的一种,也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
六. 归并排序

归并排序是采用分治法(把复杂问题分解为相对简单的子问题,分别求解,最后通过组合起子问题的解的方式得到原问题的解)的一个非常典型的应用。归并排序的思想就是先递归分解数组,再合并数组

将数组分解最小之后,然后合并两个有序数组,基本思路是比较两个数组的最前面的数,水小九先取谁,取了后相应的指针就往后移一位。然后比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来即可

Ⅷ Excel表格排序的几种方法

方法一:日期按时间排序
进入到操作界面,如图所示,首先选中需要排序的单元格区域,在选中开始菜单上的“数据”,至“排序”选项卡,在弹出的“自定义排序次序”中找到日期的排序方式即可,然后在点击确定即可完成操作,如图所示:
相关教程:excel输入日期
现在我们来预览排序完成后的效果吧。如图所示:
方法二:数据按住数字大小排序
进入到操作几面,小编随便输入几个数字,如图所示:
选中需要排序的单元格,在选中开始菜单上的“数据”,至“排序”选项卡,然后在点击“选项”命令,弹出“排序选项”,然后直接点击“按列排序”方式,即可这样单元格里面的数字就是按列小到大的排序了。如图所示:
方法三:名称按字母来排序
小编就随便输入几个名字。同样按照上面的方式,进入到排序选项窗口,如图所示:
然后在“排序选项”上选择“按字母排序”即可完成操作了,如图所示:
你可以还想了解:excel中如何拆分和冻结单元格
方法四:当然,这几种方式还是比较简单的,常用的几种方法。有的时候需要按别的方式排序的话,就可以再“自定义选项”中添加排序方式即可,如图所示:
以上就是Excel表格排序的几种方法。所有的排序要先选择要排序的内容,要包括每列表头,然后点“数据
-
排序
”在对话框里选择“主关键字”、或次关键字,再选择排序顺序,排序方式按从大到小或从小到大。

阅读全文

与四种常用数据排序方法相关的资料

热点内容
springboot中如何支持异步方法 浏览:147
上海商业用电的计算方法 浏览:241
髌骨软化症的治疗方法 浏览:733
装修多个灯线一般连接方法 浏览:287
大众进气管压力传感器检测方法 浏览:349
脂肪型眼袋用什么方法最安全 浏览:886
沙龙定制方法视频 浏览:73
自然跳弓的演奏方法是如何的 浏览:575
简单的炸油条方法视频 浏览:148
可用的研究方法有哪些 浏览:730
用怎样的方法可以鉴别牛奶的真假 浏览:35
宝妈关心的问题及解决方法 浏览:740
冷鲜肉怎么腌制方法 浏览:445
创维专供智能电视保护器使用方法 浏览:144
标志贴的安装方法 浏览:170
小米5闹钟铃声在哪里设置方法 浏览:220
暧气片安装方法 浏览:601
对于人文研究来说计算机方法 浏览:39
家庭地暖放水方法视频 浏览:826
导尿套使用方法 浏览:953