1. 基本思想:
每次将一个待排序的数据元素,插入到前面已经排好序的数列中的适当位置,使数列依然有序;直到待排序数据元素全部插入完为止。
2. 排序过程:
【示例】:
[初始关键字] [49] 38 65 97 76 13 27 49
J=2(38) [38 49] 65 97 76 13 27 49
J=3(65) [38 49 65] 97 76 13 27 49
J=4(97) [38 49 65 97] 76 13 27 49
J=5(76) [38 49 65 76 97] 13 27 49
J=6(13) [13 38 49 65 76 97] 27 49
J=7(27) [13 27 38 49 65 76 97] 49
J=8(49) [13 27 38 49 49 65 76 97]
- Procedure InsertSort(Var R : FileType);
- //对R[1..N]按递增序进行插入排序, R[0]是监视哨//
- Begin
- for I := 2 To N Do //依次插入R[2],...,R[n]//
- begin
- R[0] := R; J := I - 1;
- While R[0] < R[J] Do //查找R的插入位置//
- begin
- R[J+1] := R[J]; //将大于R的元素后移//
- J := J - 1
- end
- R[J + 1] := R[0] ; //插入R //
- end
- End; //InsertSort //
1. 基本思想:
每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。
2. 排序过程:
【示例】:
初始关键字 [49 38 65 97 76 13 27 49]
第一趟排序后 13 [38 65 97 76 49 27 49]
第二趟排序后 13 27 [65 97 76 49 38 49]
第三趟排序后 13 27 38 [97 76 49 65 49]
第四趟排序后 13 27 38 49 [49 97 65 76]
第五趟排序后 13 27 38 49 49 [97 97 76]
第六趟排序后 13 27 38 49 49 76 [76 97]
第七趟排序后 13 27 38 49 49 76 76 [ 97]
最后排序结果 13 27 38 49 49 76 76 97
- Procedure SelectSort(Var R : FileType); //对R[1..N]进行直接选择排序 //
- Begin
- for I := 1 To N - 1 Do //做N - 1趟选择排序//
- begin
- K := I;
- For J := I + 1 To N Do //在当前无序区R[I..N]中选最小的元素R[K]//
- begin
- If R[J] < R[K] Then K := J
- end;
- If K <> I Then //交换R和R[K] //
- begin Temp := R; R := R[K]; R[K] := Temp; end;
- end
- End; //SelectSort //
1. 基本思想:
两两比较待排序数据元素的大小,发现两个数据元素的次序相反时即进行交换,直到没有反序的数据元素为止。
2. 排序过程:
设想被排序的数组R[1..N]垂直竖立,将每个数据元素看作有重量的气泡,根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R,凡扫描到违反本原则的轻气泡,就使其向上"漂浮",如此反复进行,直至最后任何两个气泡都是轻者在上,重者在下为止。
【示例】:
49 13 13 13 13 13 13 13
38 49 27 27 27 27 27 27
65 38 49 38 38 38 38 38
97 65 38 49 49 49 49 49
76 97 65 49 49 49 49 49
13 76 97 65 65 65 65 65
27 27 76 97 76 76 76 76
49 49 49 76 97 97 97 97
- Procedure BubbleSort(Var R : FileType) //从下往上扫描的起泡排序//
- Begin
- For I := 1 To N-1 Do //做N-1趟排序//
- begin
- NoSwap := True; //置未排序的标志//
- For J := N - 1 DownTo 1 Do //从底部往上扫描//
- begin
- If R[J+1]< R[J] Then //交换元素//
- begin
- Temp := R[J+1]; R[J+1 := R[J]; R[J] := Temp;
- NoSwap := False
- end;
- end;
- If NoSwap Then Return//本趟排序中未发生交换,则终止算法//
- end
- End; //BubbleSort//
1. 基本思想:
在当前无序区R[1..H]中任取一个数据元素作为比较的"基准"(不妨记为X),用此基准将当前无序区划分为左右两个较小的无序区:R[1..I-1]和R[I+1..H],且左边的无序子区中数据元素均小于等于基准元素,右边的无序子区中数据元素均大于等于基准元素,而基准X则位于最终排序的位置上,即R[1..I-1]≤X.Key≤R[I+1..H](1≤I≤H),当R[1..I-1]和R[I+1..H]均非空时,分别对它们进行上述的划分过程,直至所有无序子区中的数据元素均已排序为止。
2. 排序过程:
【示例】:
初始关键字 [49 38 65 97 76 13 27 49]
第一次交换后
[27 38 65 97 76 13 49 49]
第二次交换后
[27 38 49 97 76 13 65 49]
J向左扫描,位置不变,第三次交换后
[27 38 13 97 76 49 65 49]
I向右扫描,位置不变,第四次交换后
[27 38 13 49 76 97 65 49]
J向左扫描
[27 38 13 49 76 97 65 49]
(一次划分过程)
初始关键字
[49 38 65 97 76 13 27 49]
一趟排序之后
[27 38 13] 49 [76 97 65 49]
二趟排序之后
[13] 27 [38] 49 [49 65]76 [97]
三趟排序之后 13 27 38 49 49 [65]76 97
最后的排序结果 13 27 38 49 49 65 76 97
各趟排序之后的状态
- Procedure Parttion(Var R : FileType; L, H : Integer; Var I : Integer);
- //对无序区R[1,H]做划分,I给以出本次划分后已被定位的基准元素的位置 //
- Begin
- I := 1; J := H; X := R ;//初始化,X为基准//
- Repeat
- While (R[J] >= X) And (I < J) Do
- begin
- J := J - 1 //从右向左扫描,查找第1个小于 X的元素//
- If I < J Then //已找到R[J] 〈X//
- begin
- R := R[J]; //相当于交换R和R[J]//
- I := I + 1
- end;
- While (R <= X) And (I < J) Do
- I := I + 1 //从左向右扫描,查找第1个大于 X的元素///
- end;
- If I < J Then //已找到R > X //
- begin R[J] := R; //相当于交换R和R[J]//
- J := J - 1
- end
- Until I = J;
- R := X //基准X已被最终定位//
- End; //Parttion //
- Procedure QuickSort(Var R :FileType; S,T: Integer); //对R[S..T]快速排序//
- Begin
- If S < T Then //当R[S..T]为空或只有一个元素是无需排序//
- begin
- Partion(R, S, T, I); //对R[S..T]做划分//
- QuickSort(R, S, I-1);//递归处理左区间R[S,I-1]//
- QuickSort(R, I+1,T);//递归处理右区间R[I+1..T] //
- end;
- End; //QuickSort//
1. 基本思想:
堆排序是一树形选择排序,在排序过程中,将R[1..N]看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。
2. 堆的定义: N个元素的序列K1,K2,K3,...,Kn.称为堆,当且仅当该序列满足特性:
Ki≤K2i Ki ≤K2i+1(1≤ I≤ [N/2])
堆实质上是满足如下性质的完全二叉树:树中任一非叶子结点的关键字均大于等于其孩子结点的关键字。例如序列10,15,56,25,30,70就是一个堆,它对应的完全二叉树如上图所示。这种堆中根结点(称为堆顶)的关键字最小,我们把它称为小根堆。反之,若完全二叉树中任一非叶子结点的关键字均大于等于其孩子的关键字,则称之为大根堆。
3. 排序过程:
堆排序正是利用小根堆(或大根堆)来选取当前无序区中关键字小(或最大)的记录实现排序的。我们不妨利用大根堆来排序。每一趟排序的基本操作是:将当前无序区调整为一个大根堆,选取关键字最大的堆顶记录,将它和无序区中的最后一个记录交换。这样,正好和直接选择排序相反,有序区是在原记录区的尾部形成并逐步向前扩大到整个记录区。
【示例】:对关键字序列42,13,91,23,24,16,05,88建堆
- Procedure Sift(Var R :FileType; I, M : Integer);
- //在数组R[I..M]中调用R,使得以它为完全二叉树构成堆。事先已知其左、右子树(2I+1 <=M时)均是堆//
- Begin
- X := R; J := 2*I; //若J <=M, R[J]是R的左孩子//
- While J <= M Do //若当前被调整结点R有左孩子R[J]//
- begin
- If (J < M) And R[J].Key < R[J+1].Key Then
- J := J + 1 //令J指向关键字较大的右孩子//
- //J指向R的左、右孩子中关键字较大者//
- If X.Key < R[J].Key Then //孩子结点关键字较大//
- begin
- R := R[J]; //将R[J]换到双亲位置上//
- I := J ; J := 2*I //继续以R[J]为当前被调整结点往下层调整//
- end;
- Else
- Exit//调整完毕,退出循环//
- end
- R := X;//将最初被调整的结点放入正确位置//
- End;//Sift//
- Procedure HeapSort(Var R : FileType); //对R[1..N]进行堆排序//
- Begin
- For I := N Div Downto 1 Do //建立初始堆//
- Sift(R, I , N)
- For I := N Downto 2 do //进行N-1趟排序//
- begin
- T := R[1]; R[1] := R; R := T;//将当前堆顶记录和堆中最后一个记录交换//
- Sift(R, 1, I-1) //将R[1..I-1]重成堆//
- end
- End; //HeapSort//
1. 选取排序方法需要考虑的因素:
(1) 待排序的元素数目n;
(2) 元素本身信息量的大小;
(3) 关键字的结构及其分布情况;
(4) 语言工具的条件,辅助空间的大小等。
2. 小结:
(1) 若n较小(n <= 50),则可以采用直接插入排序或直接选择排序。由于直接插入排序所需的记录移动操作较直接选择排序多,因而当记录本身信息量较大时,用直接选择排序较好。
(2) 若文件的初始状态已按关键字基本有序,则选用直接插入或冒泡排序为宜。
(3) 若n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序。
快速排序是目前基于比较的内部排序法中被认为是最好的方法。
(4) 在基于比较排序方法中,每次比较两个关键字的大小之后,仅仅出现两种可能的转移,因此可以用一棵二叉树来描述比较判定过程,由此可以证明:当文件的n个关键字随机分布时,任何借助于"比较"的排序算法,至少需要O(nlog2n)的时间。
这句话很重要 它告诉我们自己写的算法 是有改进到最优 当然没有必要一直追求最优
(5) 当记录本身信息量较大时,为避免耗费大量时间移动记录,可以用链表作为存储结构。
2013-03-28
1、插入排序(直接插入排序和希尔排序)
2、选择排序(直接选择排序和堆排序)
3、交换排序(冒泡排序和快速排序)
4、归并排序
5、基数排序---------------------
直接插入排序
说明:逐个将后一个数加到前面的排好的序中。在直接插入排序过程中,对其中一个记录的插入排序称为一次排序;直接插入排序是从第二个记录开始进行的,因此,长度为n的记录序列需要进行n-1次排序才能完成整个序列的排序。时间复杂度为O(n2)。
void InsertSort(elemtype x[],int n)
/*用直接插入法对x[0]-x[n-1]排序*/
{
int i,j;
elemtype s;
for(i=0;i<n-1;i++)
{
s=x[i+1];
j=i;
while(j>-1&&s.key<x[j].key)
{
x[j+1]=x[j];
j--;
}
x[j+1]=s;
}
}---------------------
希尔排序
说明:希尔排序又称缩小增量排序,增量di可以有各种不同的取法,但最后一次排序时的增量必须为1,最简单可取di+1=di/2(取小)。时间复杂度为O(n(log2n)2)。void ShellSort(elemtype x[],int n,intd[],int Number)
/*用希尔排序法对记录x[0]-x[n-1]排序,d为增量值数组*/
/*Number为增量值个数,各组内采用直接插入法排序*/
{
int i,j,k,m,Span;
elemtype s;
for(m=0;m<Number;m++)
{
Span=d[m];
for(k=0;k<Span;k++)
{
for(i=k;i<n-1;i+=Span)/*这个for之后的是“组内采用直接插入法排序”*/
{
s=x[i+Span];
j=i;
while(j>-1&&s.key<x[j].key)
{
x[j+Span]=x[j];
j-=Span;
}
x[j+Span]=s;
}
}
}
}----------------------------
直接选择排序
说明:每次将后面的最小的找出来插入前面的已排好的序中。同理,具有n个记录的序列要做n-1次排序。
时间复杂度为O(n2)。
void SelectSort(elemtype x[],int n)
/*用直接选择排序法对x[0]-x[n-1]排序*/
{
int i,j,Small;
elemtype Temp;
for(i=0;i<n-1;i++)
{
Small=i;
for(j=i+1;j<n;j++)
if(x[j].key<x[Small].key)
Small=j;
if(Small!=i)
{
Temp=x[i];
x[i]=x[Small];
x[Small]=Temp;
}
}
}--------------------------
冒泡排序
说明:两个两个比较,将大的往后移。通过第一次冒泡排序,使得待排序的n个记录中关键字最大的记录排到了序列的最后一个位置上。然后对序列中前n-1个记录进行第二次冒泡排序。。。对于n个记录的序列,共需进行n次冒泡排序。时间复杂度为O(n2)。void BubbleSort(elemtype x[],int n)
/*用冒泡排序法对x[0]-x[n-1]排序*/
{
int i,j,flag=1;
elemtype Temp;
for(i=1;i<n&&flag==1;i++)
{
flag=0;
for(j=0;j<n-i;j++)
{
if(x[j].key>x[j+1].key)
{
flag=1;
Temp=x[j];
x[j]=x[j+1];
x[j+1]=Temp;
}
}
}
}-----------------------------
快速排序
说明:又叫分区交换排序,是对冒泡排序方法的一种改进。时间复杂度为O(nlog2n)。void QuickSort(elemtype x[],int low,int high)
/*用递归方法对记录x[0]-x[n-1]进行快速排序*/
{
int i,j;
elemtype Temp; i=low;
j=high;
Temp=x[low]; while(i<j)
{
/*在序列的右端扫描*/
while(i<j&&Temp.key<=x[j].key)j--;
if(i<j)
{
x[i]=x[j];
i++;
} /*在序列的左端扫描*/
while(i<j&&x[i].key<Temp.key)i++;
if(i<j)
{
x[j]=x[i];
j--;
}
}
x[i]=Temp; /*对子序列进行快速排序*/
if(low<i-1)QuickSort(x,low,i-1);
if(j+1<high)QuickSort(x,j+1,high);
}-------------------------
归并排序
说明:所谓归并排序就是将两个或两个以上的有序数据序列合并成一个有序数据序列的过程。
时间复杂度为O(nlog2n)。void merge(r,l,m,h,r1,r2)/*r[l,m]及r[m+1,h]分别有序,归并后置于r2中*/
sqlist r,r2;
int l,m,h;
{
int i,j,k;
k=l;/*k是r2的指示器,i、j分别为s1、s2的指示器*/
i=l;
j=m+1; while(i<=m&&j<=h)
{
if(r[i].key<=r[j].key)
{
r2[k]=r[i];
i++;
}
else
{
r2[k]=r[j];
j++;
}
k++;
}
if(i>m) /*s1结束*/
while(j<=h)
{
r2[k]=r[j];
j++;k++;
}
else
while(i<=m)
{
r2[k]=r[i];
i++;k++;
}
}
参考自: http://blog.csdn.net/zgbsoap/archive/2005/11/14/529202.aspx
排序法可分为简单排序法和交替排序法。
简单排序法
简单排序法也称序列评定法,是指管理者把本部门的所有员工从绩效最高者到绩效最低者(或从最好者到最差者)进行排序,即对一批考核对象按照一定标准排出“1、2、3、4……”的顺序。
该方法也应用也工作评价上,由负责工作评价的人员,根据其对企业各项工作的经验认识和主观判断,对各项工作在企业中的相对价值进行整体的比较,并加以排队。在对各项工作进行比较排序时,一般要求工作评价人员综合考虑以下各项因素:工作职责、工作权限、岗位资格、工作条件、工作环境等。权衡各项工作在各项因素上的轻重程度并排定秩序后,将其划入不同的工资等级内。
简单排序法的优点:该方法的优点是简便易行,具有一定的可信性,可以完全避免趋中倾向或宽严误差。
缺点是考核的人数不能过多,以5—15人为宜,而且只适用于考核同类职务的人员,应用范围受限,不适合在跨部门人事调整方面应用。
交替排序法
交替排序法则是指管理者对被评估员工的名单进行审查后,从中找出工作绩效最好的员工列为第一名,并将其的名字从名单上划去。然后从剩下的名单中找出工作绩效最差的员工排为最后一名,也把其名字从名单中划去。随后,在剩下的员工中管理者再找出一名工作绩效最好的员工将其排为第二名,找出一名最差的员工列为倒数第二名,以此类推,直到将所有的员工排序完。