排序与查找
1.冒泡排序 : 若有n个元素,第一个元素和第2个元素比较, 若为逆序,则交换,然后比较第2个和第3个元素,依次类推,直到第n - 1和n 进行过比较为止, 这称为第一躺冒泡,结果使最大的元素被安置到了最后一个元素的位置上,然后进行第二躺冒泡,参与比较的元素个数为n-1, 依次类推, 冒泡躺数位K(1 <= k < n)
1 int maopao_sort(int a[], int len) 2 { 3 int i = 0, j = 0; 4 int itemp = 0; 5 6 for(i = 0; i != len - 1; i ++) 7 { 8 for(j = 0; j != len - 1 - i; j ++) 9 { 10 if(a[j] > a[j + 1]) { 11 itemp = a[j]; 12 a[j] = a[j + 1]; 13 a[j + 1] = itemp; 14 } 15 } 16 } 17 18 return 0; 19 }
2.选择排序 : 每一躺在n - i + 1(i = 1, 2 ..., n - 1)个元素中选取最小的元素作为有序序列中第i个元素
19 int choose_sort(int a[], int len) 20 { 21 int i = 0, j = 0, k = 0; 22 int itemp = 0; 23 #if 0 24 for(i = 0; i != len; i ++) 25 { 26 for(j = i + 1; j != len; j ++) 27 { 28 if(a[i] > a[j]) { 29 itemp = a[i]; 30 a[i] = a[j]; 31 a[j] = itemp; 32 } 33 } 34 } 35 #else 36 for(i = 0; i != len; i ++) 37 { 38 k = i; 39 for(j = i + 1; j != len; j ++) 40 { 41 if(a[k] > a[j]) { 42 k = j; 43 } 44 } 45 46 if(k != i) { 47 itemp = a[i]; 48 a[i] = a[k]; 49 a[k] = itemp; 50 } 51 } 52 #endif 53 54 return 1; 55 }
3.插入排序 : 在已排序的n个元素中插入一个新的元素, 得到有序的n + 1个元素, 当只有一个元素时,默认是排好序的
88 int insert_sort(int a[], int len) 89 { 90 int i = 0, j = 0; 91 int itemp = 0; 92 93 for(i = 0; i != len - 1; i ++) 94 { 95 itemp = a[i + 1]; 96 for(j = i; itemp < a[j] && j >= 0; j --) 97 { 98 a[j + 1] = a[j]; 99 } 100 a[j + 1] = itemp; 101 } 102 103 return 0; 104 }
4.归并排序 : 将两个或两个以上的有序表组合成一个新的有序表
1 void merger_sort_achieve(int a[], int begin, int end, int m) 2 { 3 int i = 0, j = 0, k = 0; 4 int b[end + 1]; 5 6 for(i = begin; i != end + 1; i ++) 7 { 8 b[i] = a[i]; 9 } 10 11 i = begin; 12 j = m + 1; 13 k = begin; 14 15 while(i <= m && j <= end) 16 { 17 if(b[i] > b[j]) { 18 a[k ++] = b[j ++]; 19 } 20 else { 21 a[k ++] = b[i ++]; 22 } 23 24 while(i <= m) 25 { 26 a[k ++] = b[i ++]; 27 } 28 while(j <= m) 29 { 30 a[k ++] = b[j ++]; 31 } 32 } 33 34 } 35 36 int merger_sort(int a[], int begin, int end) 37 { 38 int m = 0; 39 40 if(begin >= end) { 41 return 1; 42 } 43 44 m = (begin + end) / 2; 45 merger_sort(a, begin, m); 46 merger_sort(a, m + 1, end); 47 merger_sort_achieve(a, begin, end, m); 48 49 return 0; 50 }
5.快速排序 : 选取1个分割元素,通过一趟排序,将待排序元素分成独立的两部分,其中一部分元素均比另一部分的元素小,以所选分割元素为份界点, 则可分别对这两部分元素继续进行排序(可递归实现), 以达到整个序列有序
29 void exercise_sort(int a[], int begin, int end) 30 { 31 int cut = 0; 32 33 if(begin >= end) { 34 return ; 35 } 36 37 cut = cut_number(a, begin, end); 38 exercise_sort(a, begin, cut - 1); 39 exercise_sort(a, cut + 1, end); 40 41 } 42 43 int cut_number(int a[], int begin, int end) 44 { 45 int i = 0, j = 0; 46 47 for(i = begin + 1, j = begin; i <= end; i ++) 48 { 49 if(a[begin] > a[i]) { 50 swap(&a[i], &a[++ j]); 51 } 52 } 53 swap(&a[begin], &a[j]); 54 55 return j; 56 } 57 58 void swap(int *a, int *b) 59 { 60 int itemp = 0; 61 itemp = *a; 62 *a = *b; 63 *b = itemp; 64 65 return ; 66 }
排序选择
1.若n较小(如n <= 50), 可采用插入或选择排序。
当记录规模较小时, 插入排序较好, 否则因为选择移动的元素数少于插入,应选直接选择排序为宜。
2.若文件初始状态基本有序,则应选用直接插入, 冒泡或随机的快速排序为宜
3.若n较大, 则应采用时间复杂度为0(nlgn)的排序方法: 快速排序或归并排序
快速排序是目前基于比较的内部排序中被认为是最好的方法, 当待排序的关键字是随机分布时, 快速排序的平均时间最短
4.若要求排序稳定, 则可选用归并排序
排序性能分析
稳定性 : 如果存在多个具有相同排序码的元素, 经过排序后,这些元素的相对次序仍然保持不变,则这种排序算法称为稳定的
排序稳定的 : 插入排序,冒泡排序,归并排序。
排序不稳定的 : 选择排序, 快速排序
时间复杂度 :
n^2 (慢的):冒泡排序, 选择排序, 插入排序
nlgn(快的) :归并排序, 快速排序
二分查找
1. 使用条件 : 只有在有序表中查找元素才可使用
2. 折半查找 : 序列已经从小到大排好序了, 每次取中间元素和待查找的元素比较,如果中间的元素比待查找的元素小,就说明“如果待查找的元素存在,一定位于序列的后半部分”, 这样可以把搜索范围缩小到后半部分,然后再次使用这种算法迭代。这种“每次把搜索范围缩小一半”的思想称为折半查找
位图思想
1.使用条件:
输入数据限制在相对较小的范围内,
数据没有重复,,
且除了单一整数外,么有任何其他关联数据
2.例子 : 比如集合{1, 2, 3, 5, 8, 13}
可以使用两个字节的16位记录
位图表示为 :
0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0
3.排序思想
n / 32 与 n % 32
计算n对应位图的位置
置1 : set(int a[], int n)
清0 : clean(int a[], int n)
查找:int bitmap_search(int a[], int n)
英语 : achieve(实现) insert(插入) merger(归并) cutting elemet(切割元素) record(记录)