基础算法:排序、散列、递归、贪心、二分以及其他高效技巧
1.排序:
排序主要可以分为:选择排序、插入排序
选择排序:
主要介绍最为常用的简单选择排序
简单选择排序:基本思路是将一个序列分为1~n个单元,首先从这n个单元里选择出来最小的单元,将其与第一个位置的单元相交换,接着从2~n个单元里,找出最小单元,将其与第二个位置的单元相交换,依次进行下去......。这样在n趟操作之后就会形成一个从小到大的有序序列。
代码实现:一共进行n次操作,嵌套for循环,每次找出从i到n之中最小的数,然后与第i个位置数据进行交换
void SelectSort( int a[], int length ) { //对数组a排序,length是数组元素数量 for( int i = 0; i < length; i++ ) { // 找到从i开始到最后一个元素中最小的元素,k存储最小元素的下标. int k = i; for( int j = i + 1; j < length; j++ ) { if( a[j] < a[k] ) { k = j; } } // 将最小的元素a[k] 和 开始的元素a[i] 交换数据. if( k != i ) { int temp; temp= a[k]; a[k] = a[i]; a[i] = temp; } } }
插入排序:
主要介绍直接插入排序
直接插入排序:从2~n进行n-1次操作。假设这个时候是第i+1个数据,且前面1~i个数据均为有序数据,则将第i个数据插入到前面数据之中,因此可以采用for循环从2~n,内部嵌套上while循环,进行查找1~i之中第i+1个数据适合放在哪里。
void SelectSort(){ for(int i=1;i){ int temp = A[i], j=i; while(j>0 && temp1]){ A[j] = A[j-1]; j--; } A[j] = temp; } }
实例:
#includeusing namespace std; int main(){ int num[5] = {3, 7, 1, 8, 5}; int i,j; int length = 5; for (i = 1; i < length; i++) { int temp = num[i]; j = i; while ( j > 0 && num[j-1] > temp) { num[j] = num[j-1]; j--; } num[j] = temp; } for(int k=0;k //打印数组 cout<<num[k]; } return 0; } 结果:13578
选择排序之实例剖析:
#includeusing namespace std; const int MAX_NUM = 100; //选择排序 int main(){ int a[MAX_NUM]; int n; cin >> n; //共有n个整数待排序 for(int i = 0; i < n; ++i) //输入n个整数 cin >> a[i]; //下面对整个数组进行从小到大排序 for(int i = 0; i 1 ;++i){ //每次循环将第i小的元素放好 int tmpMin = i; //用来记录从第i个到第n-1个元素中,最小的那个元素的下标 for(int j=i; j j){ if(a[j]<a[tmpMin]) tmpMin = j; } //下面将第i小的元素放在第i个位置上,并将原来占着第i个位置的那个元素挪到后面 int tmp = a[i]; a[i] = a[tmpMin]; a[tmpMin] = tmp; } //下面两行将排序好的n个元素输出 for(int i=0;i i) cout << a[i] << endl; return 0; }
插入排序之实例剖析:
#includeusing namespace std; //插入排序 void InsertionSort(int a[], int size) { int i; //有序区间的最后一个元素的位置,i+1就是无序区间最左边元素的位置 for(i = 0; i < size-1; ++i){ int tmp = a[i + 1]; //tmp是待插入到有序区间的元素,即无序区间最左边的元素 int j = i; while(j >= 0 && tmp < a[j]){ //寻找插入的位置 a[j + 1] = a[j]; //比tmp大的元素都往后移动 --j; } a[j + 1] = tmp; } } //输出二维数组,rows是行数 void PrintArray(int a[][5], int rows) { for(int i = 0; i < rows; ++i){ for(int j = 0; j < 5; ++j) cout << a[i][j] << " "; cout << endl; } } //主函数 int main(){ int b[5] = {50, 30, 20, 10, 40}; int a2d[3][5] = {{5, 3, 2, 1, 4},{10, 20, 50, 40, 30},{100, 120, 50, 140, 30}}; InsertionSort(b, 5); for(int i = 0; i < 5; ++i) cout << b[i] << " "; cout << endl; for(int i = 0; i < 3; ++i) //将 a2d每一行均排序 InsertionSort(a2d[i], 5); PrintArray(a2d, 3); return 0; }
2.散列
哈希表(也可以叫做散列表),是根据 键(Key)而直接访问在内存存储位置的数据结构,也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做哈希表。
哈希函数构造:
如果字符串S由A~Z组成:
如果字符串S由A~Z/a~z组成:
3.全排列问题(递归):
//全排列:视频参考哔哩哔哩:正月点灯笼 #includevoid swap(int A[], int i, int j){//用于交换数组的2个值 int temp = A[i]; A[i] = A[j]; A[j] = temp; } void printArray(int A[], int n){//用于打印数组 int i; for(i=0;i ){ printf("%d ", A[i]); } printf("\n"); } void perm(int A[], int p, int q){//全排列递归函数;p,q代表对数组A全排列的起始和结束 if(p == q){//递归结束条件 printArray(A, q+1); } else{ int i; for(i=p; i<=q; i++){ swap(A, p, i); perm(A, p+1, q); swap(A, p, i); } } } int main(){ int A[4] = {1, 2, 3, 4}; perm(A, 0, 3); return 0; }
4.N皇后问题: