190 likes | 339 Views
排序和查找. 关于排序. 排序是数据处理中经常遇到的一种重要运算,其功能是按某种指定的顺序将一个数据元素的无序序列调整成为一个有序序列。 排序方法有选择排序、冒泡排序、插入排序等,下面复习这几种排序方法。. 1. 选择排序 例 1 : #define N 10 void SelSort(int a[N]) /* 选择排序函数* / { int i, j, minj, t; for(i=0; i<N-1; i++) { minj=i;
E N D
关于排序 排序是数据处理中经常遇到的一种重要运算,其功能是按某种指定的顺序将一个数据元素的无序序列调整成为一个有序序列。 排序方法有选择排序、冒泡排序、插入排序等,下面复习这几种排序方法。
1.选择排序 例1: #define N 10 void SelSort(int a[N]) /*选择排序函数*/ { int i, j, minj, t; for(i=0; i<N-1; i++) { minj=i; for(j=i+1; j<N; j++) if(a[j]<a[minj]) minj=j; if(minj!=i) { t=a[i]; a[i]=a[minj]; a[minj]=t; } } }
void main() { int a[N],i; for(i=0; i<N; i++) scanf("%d", a+i); SelSort(a); for(i=0; i<N; i++) printf("%6d", a[i]); }
2.冒泡排序 例2: #define N 10 void main() { int a[N], i, j, t; printf("Input %d numbers:\n", N); for(i=0; i<N; i++) scanf("%d", a+i); for(i=1; i<N; i++) for(j=0; j<N-i; j++) if(a[j]>a[j+1]) { t=a[j]; a[j]=a[j+1]; a[j+1]=t; } printf("Reslut:"); for(i=0; i<N; i++) printf("%6d", a[I]); printf("\n"); }
*冒泡排序的改进: 显然,当数组已经排好序时,不会发生元素的浮 动(即元素的交换值),因此,可设一个标变量,当 内循环未发生前后两元素交换值时, 就跳出外循环。 void BubSort(int a[N]) { int i, j, t, sorted; for(i=1; i<N; i++) { sorted=1; for(j=0; j<N-i; j++) if(a[j]>a[j+1]) { t=a[j]; a[j]=a[j+1]; a[j+1]=t; sorted=0;} if(sorted) break; } }
*3.插入排序 算法: N元数组a[0]~a[N-1]由小到大排序: 第1步:将a[1]插入a[0]~a[1]中,使得a[0]~a[1]升序; 第2步:将a[2]插入a[0]~a[2]中,使得a[0]~a[2]升序; 第3步:将a[3]插入a[0]~a[3]中,使得a[0]~a[3]升序;… 第i步:将a[i]插入a[0]~a[i]中,使得a[0]~a[i]升序; … 第N-1步:将a[N-1]插入a[0]~a[N-1]中,使得 a[0]~a[N-1]升序;算法停止。
例3: #define N 10 void InsSort(int a[N]) /*N元数组插入排序*/ { int i, j, x;for(i=1; i<N; i++){ x=a[i]; j=i-1; while(j>=0&&a[j]>x) { a[j+1]=a[j]; j--; } a[j+1]=x;} } void main() { int a[N], i;for(i=0; i<N; i++) scanf("%d", &a[i]);InsSort(a);for(i=0; i<N; i++) printf("%6d", a[i]); }
关于查找 查找是数据结构的基本运算之一。 从数据元素表(比如数组)中找出满足某种条 件的数据元素的操作是查找运算。查找可能查到, 也可能查不到。要有结论。
1.顺序查找 又称线性查找,它是最简单的基于关键字值的查找方法。 算法:用待查的关键字值与线性表中各数据元素逐个顺序比较,若找出相等值的数据元素则查找成功,否则查找失败。 例1: #include <stdio.h> #include <string.h> char *name[]={"zhao","qian","sun","li","wang", "chen","liu","zhang"};
main() { char **first, **last, **mid; char search[10]; int i, j, k; printf("Please input the name:"); gets(search); first=name; last=name+sizeof(name)/sizeof(char *); while(first<=last) if(strcmp(*first, search)!=0) first++; else { printf("Have found it!,name:%s\n",*first); break; } if(first>last) printf("The name isn't exist!"); }
顺序查找的优点: 对线性表中数据元素的次序无任何要求,不必按关键字值排序;对线性表的存储结构无特殊要求,顺序存储、链接存储均可。 顺序查找的缺点: 查找效率低。比如有n个数据元素,则比较次数最少一次,最多为n次,平均比较次数为n/2次,不适宜快速查找。
2.二分法查找 又称为折半查找、对分查找,它是一种效率较 高的线性表查找方法,为人们常用。这种查找不仅 基于关键字值查找,而且要求线性表中数据元素必 须按关键字值排序,并且以顺序方式存储。
算法: 设a[0]~a[N-1]已升序,待查找元素为x 令起点下标 h=0; 终点下标 r=N-1; 中点下标 m=(h+r)/2; @ 当h<=r时执行以下步骤: 若x==a[m],则表明查找成功,a[m]为所找元素; x<a[m],显然x在a[h]~a[m-1]之间,则h不变; r=m-1; m=(h+r)/2; 转@ x>a[m],显然x在a[m+1]~a[r]之间,则r不变; h=m+1; m=(h+r)/2; 转@ 若h>r,则表明查找失败.
例2: main() { int a[10]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int b, s; scanf("%d",&s); b=locate(a, 10, s); if(b==-1) printf("The number isn't in the array!\n"); else printf("The number is in the array!\n"); }
int locate(int a[], int n, int x) { int h, r, m; h=0; r=n-1; m=(h+r)/2; while(h<=r&&x!=a[m]) if(x<a[m]) { r=m-1; m=(h+r)/2; } else { h=m+1; m=(h+r)/2; } if(h>r) return -1; return m; }
二分法查找的优点: 每经过一次关键字比较,则删除表中一半元素,使得查找范围小一半,提高了查找速度,如果对有n个元素的表,采用二分法查找,一般经log2n次比较就可完成。 二分法查找的缺点: 在查找开始前必须在排序上花费时间,并且以顺序方式存储,删除与插入均不方便。
练习题 1、编函数int fun(int *a, int *n, int pos[]), 其功能是: 在含有10个元素的数组s中查找最大数,及最大数 的下标值,最大数可能不止一个。最大数作为函 数值返回,最大数的个数通过指针变量n传回,所 在位置由数组pos传回。 2、编一个程序,其功能是:读入十个整数存入一 维数组m中,输出该数组中最大元素的下标。
3、编一个函数void sort(char **q),它的功能是: 对五个字符串进行排序。五个字符串由主函数 main通过键盘输入。 4、编一个程序,读入十个整数存入一维数组n中, 输出该数组中所有素数的和。