目录
一、算法原理
-
顺序查找:
- 就是从数组的第一个元素开始,依次比较,直到找到目标数据或查找失败。
-
折半查找:
- 首先计算表中间的位置,将表中间位置处的关键字与查找的关键字进行比较,如果相等,则查找成功;否则利用中间位置将表分为前、后两个子表,如果中间位置的关键字大于查找的关键字,则查找前子表,否则查找后子表。重复上面的过程,直到找到要查找的关键字为止,否则查找失败不存在此关键字。
-
选择排序:
- 从头至尾扫描序列,找出最小的一个元素,和第一个元素交换,接着从剩下的元素中继续这种选择和交换方式,最终得到一个有序序列。
-
冒泡排序:
- 相邻的元素两两比较,较大的数下沉,较小的数冒起来,这样一趟比较下来,最大(小)值就会排列在一端。
-
快速排序:
- 每趟排序时选出一个基准值,然后将所有元素与该基准值比较,并按大小分成左右两堆,然后递归执行该过程,直到所有元素都完成排序。
-
二、算法实现
-
顺序查找和折半查找的实现
-
//顺序查找和折半查找的源代码 #include <iostream> using namespace std; //数据存储结构 typedef struct { int *elem; int length; }Table; //顺序查找算法 int Search(Table table , int key){ table.elem[0] = key; int i; for(i = table.length-1;table.elem[i] != key;--i); return i; } //折半查找 int Binary_search(Table table,int key) { int low=1,high=table.length,mid; while(low<high){ mid = (low+high)/2; if(table.elem[mid] == key){ return mid; }else if(table.elem[mid]<key){ low = mid + 1; }else{ high = mid-1; } } return 0; } int main () { Table T ; int a[10] = {0,1,2,3,4,5,6,7,8,9}; //0是为哨兵所留位置 (节省判断数组下标越界的代码的方法) T.elem = a; T.length = sizeof(a)/sizeof(int); if(Search(T,5) == 0) cout<<"查找失败!"<<endl; else cout<<Search(T,5)<<endl; if(Binary_search(T,6) == 0 ) cout<<"查找失败!"<<endl; else cout<<Binary_search(T,6)<<endl; return 0; }
选择排序的实现:
-
#include<stdio.h> #define MAXNUM 100 #define TRUE 1 #define FALSE 0 typedef int KeyType; typedef int DataType; typedef struct { KeyType key; /* 排序码字段 */ /*DataType info; 记录的其它字段 */ } RecordNode; typedef struct { int n; /* n为文件中的记录个数,n<MAXNUM */ RecordNode record[MAXNUM]; } SortObject; void selectSort(SortObject * pvector) { /* 按递增序进行直接选择排序 */ int i, j, k; RecordNode temp, *data = pvector->record; for( i = 0; i < pvector->n-1; i++ ) { /* 做n-1趟选择排序 */ k = i; for (j = i+1; j < pvector->n; j++) /* 在无序区内找出排序码最小的记录Rk*/ if (data[j].key < data[k].key) k = j; if (k != i) { /* 记录Rk与Ri互换 */ temp = data[i]; data[i] = data[k]; data[k] = temp; } } } SortObject vector={8, 49,38,65,97,76,13,27,49}; int main() { int i; selectSort(&vector); for(i = 0; i < 8; i++) printf("%d ", vector.record[i]); getchar(); return 0; }
冒泡排序的实现:
-
#include<stdio.h> #define MAXNUM 100 #define TRUE 1 #define FALSE 0 typedef int KeyType; typedef int DataType; typedef struct { KeyType key; /* 排序码字段 */ /*DataType info; 记录的其它字段 */ } RecordNode; typedef struct { int n; /* n为文件中的记录个数,n<MAXNUM */ RecordNode record[MAXNUM]; } SortObject; void bubbleSort(SortObject * pvector) { int i, j, noswap; RecordNode temp, *data = pvector->record; for(i = 0; i < pvector->n-1; i++) { /* 做n-1次起泡 */ noswap = TRUE; /* 置交换标志 */ for (j = 0; j < pvector->n-i-1; j++) /* 从前向后扫描 */ if (data[j+1].key < data[j].key) { /* 交换记录 */ temp = data[j]; data[j] = data[j+1]; data[j+1] = temp; noswap = FALSE; } if ( noswap ) break; /* 本趟起泡未发生记录交换,算法结束 */ } } SortObject vector={8, 49,38,65,97,76,13,27,49}; int main() { int i; bubbleSort(&vector); for(i = 0; i < 8; i++) printf("%d ", vector.record[i]); getchar(); return 0; }
快速排序的实现:
-
#include<stdio.h> #define MAXNUM 100 #define TRUE 1 #define FALSE 0 typedef int KeyType; typedef int DataType; typedef struct { KeyType key; /* 排序码字段 */ /*DataType info; 记录的其它字段 */ } RecordNode; typedef struct { int n; /* n为文件中的记录个数,n<MAXNUM */ RecordNode record[MAXNUM]; } SortObject; void quickSort(SortObject * pvector, int l, int r) { int i, j; RecordNode temp, *data = pvector->record; if (l >= r) return; /* 只有一个记录或无记录,则无须排序 */ i = l; j = r; temp = data[i]; while (i != j) { /* 寻找Rl的最终位置 */ while( data[j].key >= temp.key && j > i ) j--; /* 从右向左扫描,查找第1个排序码小于temp.key的记录 */ if (i < j) data[i++] = data[j]; while( data[i].key <= temp.key && j > i ) i++; /* 从左向右扫描,查找第1个排序码大于temp.key的记录 */ if (i < j) data[j--] = data[i]; } data[i] = temp; /* 找到Rl的最终位置 */ quickSort(pvector, l, i-1); /* 递归处理左区间 */ quickSort(pvector, i+1, r); /* 递归处理右区间 */ } SortObject vector = {8, 49,38,65,97,76,13,27,49}; int main() { int i; quickSort(&vector, 0, 7); for(i = 0; i < 8; i++) printf("%d ", vector.record[i]); getchar(); return 0; }
三、复杂度分析
-
顺序查找:
-
最好的情况是数组的第 1 个元素就是我们要找的元素,这样可以直接找到。此时时间复杂度为O(1),最坏的情况是到最后一个元素时才找到或者没有找到要找的元素,时间复杂度为O(n)。查找成功时的平均查找长度为:(假设每个数据元素的概率相等) ASL = 1/n(1+2+3+…+n) = (n+1)/2 ;当查找不成功时,需要n+1次比较,时间复杂度为O(n); 所以,顺序查找的时间复杂度为O(n)。
顺序查找是对数列顺序的比较,没有额外的空间,所以空间复杂度为常数 O(1)。
-
二分查找:
-
最好的情况是只查找一次就能找到,但是在最坏和一般情况下比顺序查找好了很多。二分查找的平均查找长度 ASL 为log2(n+1)-1,所以二分查找的时间复杂度为 O(log2n)。二分查找的空间复杂度为O(1)。
-
快速排序:
-
快速排序最优的情况就是每一次取到的元素都刚好平分整个数组,最优的情况下时间复杂度为:O( nlogn )。最差的情况就是每一次取到的元素就是数组中最小/最大的,这种情况其实就是冒泡排序了,最差的情况下时间复杂度为:O( n^2 )。快速排序的平均时间复杂度也是:O(nlogn)。
最优(每一次都平分数组)的情况下空间复杂度为:O(logn);最差(退化为冒泡排序)的情况下空间复杂度为:O( n )。
-
选择排序:
-
直接选择排序关键字比较次数永远是比较n(n-1)/2次,记录移动最少0次,最多3(n-1)次。所以,直接选择排序的时间复杂度是O(n^2)。它的空间复杂度是O(1)。
-
冒泡排序:
-
冒泡排序最好是关键字有序,n个关键字比较n-1次,记录移动0次。最坏是完全逆序,关键字比较n(n-1)/2次,记录移动3n(n-1)/2次。所以,冒泡排序的时间复杂度为O(n^2)。因为只是用了2个循环变量以及1到2个标志和交换等的中间变量,这个与待排序的记录个数无关,所以空间复杂度是O(1)。