排序
来源:互联网 发布:网络推广主要做什么 编辑:程序博客网 时间:2024/04/27 06:44
一,什么是排序?
排序是计算机内经常进行的一种操作,其目的是将一组"无序"的记录序列调整为"有序"的记录序列
排序的定义
假设含n个记录的序列为{ R1, R2, …, Rn }其相应的关键字序列为 { K1, K2, …,Kn }这些关键字相互之间可以进行比较,即在它们之间存在着这样一个关系 :Kp1≤Kp2≤…≤Kpn按此固有关系将上式记录序列重新排列为{ Rp1, Rp2, …,Rpn }的操作称作排序。
二,内部排序和外部排序
若整个排序过程不需要访问外存便能完成,则称此类排序问题为"内部排序";反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中完成,则称此类排序问题为"外部排序"。
排序方法还可分为"稳定的排序"和"不稳定的排序"
#define MAXSIZE 1000//待排序的记录数目typedef int KeyType;//关键字类型为整数类型typedef struct{ KeyType key;//关键字项 InfoType otherinfo;//其他数据项}RecordType;//记录类型typedef struct{ RecordType r[MAXSIZE+1]; int length;//序列长度,即记录个数}RecordList;//记录序列类型,及顺序表类型RecordList L;
插入类排序
直接插入排序
直接插入排序举例:48 62 35 77 55 14 *35 98-48 -62 35 77 55 14 *35 98-35 -48 -62 77 55 14 *35 98-35 -48 -62 -77 55 14 *35 98-35 -48 -55 -62 -77 14 *35 98-14 -35 -48 -55 -62 -77 *35 98-14 -35 -*35 -48 -55 -62 -77 98-14 -35 -*35 -48 -55 -62 -77 -98
//直接插入排序void InsertSort(RecordType r[],int length){ int i,j; for(i=2;i<=length;i++) { r[0]=r[i];/*将待插入记录存放到监视哨r[0]中*/ j=i-1; while(r[0].key<r[j].key)/*寻找插如位置*/ { r[j+1]=r[j]; j=j-1; } r[j+1]=r[0];/*将待插入记录插入到已排序的序列中*/ }}
折半插入排序
void BinSort(RecordType r[],int length){ int i,j; RecordType x; int low,high,mid; for(i=2;i<=length;i++) { x=r[i]; low=1; high=i-1; while(low<=high)/*确定插入位置*/ { mid=(low+high)/2; if(x.key<r[mid].key) high=mid-1; else low=mid+1; } for(j=i-1;j>=low;j--) r[j+1]=r[j];/* 记录依次向后移动 */ r[low]=x;/* 插入记录 */ }}
希尔排序
void ShellInsert(RecordType r[], int length, int delta) { int i,j; //希尔排序 for(i=1+delta;i<= length; i++) if(r[i].key < r[i-delta].key) { r[0]= r[i]; for(j=i-delta; j>0 &&r[0].key < r[j].key; j-=delta) r[j+delta]= r[j]; r[j+delta]= r[0]; }}void ShellSort(RecordType r[], int length, int delt[], int n){ int i; for(i=0 ; i<=n-1; ++i) ShellInsert(r, length, delt[i]);}
交换类排序
冒泡排序
//一个记录序列的关键字分别为46,25,68,33,*33,19,12,80第一趟:25 46 33 *33 19 12 68 80第二趟:25 33 *33 19 12 46 68 80第三趟:25 33 19 12 *33 46 68 80第四趟:25 19 12 33 *33 46 68 80第五趟:19 12 25 33 *33 46 68 80第六趟:12 19 25 33 *33 46 68 80第七趟:12 19 25 33 *33 46 68 80
//冒泡排序void BubbleSort(RecordList L){ flag=1; for(i=1;i<=L.length-1 && flag;i++) { flag=0; for(j=1;j<=L.length-i;j++) { if(L.r[j].key>L.r[j+1].key) { t=L.r[j]; L.r[j]=L.r[j+1]; L.r[j+1]=t; flag=1; } } }}
快速排序
目标:找一个记录,以它的关键字作为“枢轴”,凡其关键字小于枢轴的记录均移动至该记录之前,反之,凡关键字大于枢轴的记录均移动至该记录之后。致使一趟排序之后,记录的无序序列R[s..t]将分割成两部分R[s..i-1]和R[i+1..t],且R[j].key≤ R[i].key ≤ R[j].key(s≤j≤i-1) 枢轴 (i+1≤j≤t)。
一趟快速排序过程
据结构 第九章 排序一趟快速排序int QKPass(RecordType r[],int left,int right){ RecordType x; int low,high; x= r[left]; low=left; high=right; while ( low<high ) { while (low< high && r[high].key>=x.key ) high--; if ( low <high ) { r[low]= r[high]; low++; } while (low<high && r[low].key<x.key ) low++; if ( low<high ) /* 找到大于x.key的记录,则交换*/ { r[high]= r[low]; high--; } } r[low]=x; /*将基准记录保存到low=high的位置*/ return low; /*返回基准记录的位置*/}void QKSort(RecordType r[],int low, int high ){ int pos; if(low<high) { pos=QKPass(r, low, high); /*将枢轴元素为界划分两个子表*/ QKSort(r, low, pos-1); /*对左部子表快速排序*/ QKSort(r, pos+1, high); /*对右部子表快速排序*/ }}
选择类排序
简单选择排序
void SelectSort(RecordType r[], int length){ int i,j,k; int n; RecordType x; n=length; for ( i=1 ; i<= n-1; ++i) { k=i; for ( j=i+1 ; j<= n ; ++j) if (r[j].key < r[k].key ) k=j; if ( k!=i) /* 进行记录的交换*/ { x= r[i]; r[i]= r[k]; r[k]=x; } }}
时间复杂度:对n个记录进行简单选择排序,所需进行的关键字间的比较次数总计为
空间复杂度:需要一个辅助空间用于交换,故为O(1)
稳定性:不稳定
树形选择排序
12 19 25 33 33 46 68 80
堆排序
堆的筛选
**一个记录序列的关键字为46,12,33,72,68,19,80,33,建立初始堆
归并排序
二路归并排序
void Merge(RecordType r1[], int low, int mid,int high, RecordType r2[]){ int i,j,k; i=low; j=mid+1; k=low; while ( (i<=mid)&&(j<=high) ) { if ( r1[i].key<=r1[j].key ) { r2[k]=r1[i]; ++i; } else { r2[k]=r1[j]; ++j; } ++k; } while( i<=mid ) { r2[k]=r1[i]; k++; i++; } while( j<=high) { r2[k]=r1[j]; k++; j++; }}
分配类排序
基数排序
各种排序方法综合比较
0 0