1.查找
折半查找:通过中间值来判断,如果值小于n往右半轴移动,大于则往左半轴。注意折半查找需要时有序表,时间复杂度时O(logn)。
#include <stdio.h>
#include <stdlib.h>
int Search(int list[],int len,int n){
int low=0;
int high=len-1;
int mid;
while (low<high)
{
mid=(low+high)/2;
if(list[mid]==n){ //如果等于输出
return n;
}else if(list[mid]>n){ //如果中间值比n大,high移到mid左边,往左半轴移动
high=mid-1;
}else{ //如果中间值比n小,low移到mid右边,往右半轴移动
low=mid+1;
}
}
return -1;
}
int main(){
int list[]={7, 16, 27, 38, 42, 59, 65, 73, 84, 92};
int a=Search(list,10,27);
if(a!=-1){
printf("%d",a);
}else{
printf("err");
}
}
2.排序
下面所有排序都是升序
直接插入:
void sort_Insert(int list[],int n){ //直接插入排序
int i,j;
for(i=1;i<=n;i++){ //依次将list[2]-list[n]插入前面已排好的序列
if(list[i]<list[i-1]){ //若A[i]关键码小于其前驱,将A[i]插入有序表
list[0]=list[i]; //复制为哨兵,A[0]不放元素
for(j=i-1;list[0]<list[j];j--){ //从后往前查找待插入位置
list[j+1]=list[j]; //向后挪位
}
list[j+1]=list[0]; //复制到插入位置
}
}
}
冒泡:注意第二层循环截至是n-i-1
void sort_Bubble(int list[],int n){ //冒泡排序
for(int i=0;i<n;i++){
for(int j=0;j<n-i-1;j++){
if(list[j]>list[j+1]){
int temp=list[j];
list[j]=list[j+1];
list[j+1]=temp;
}
}
}
}
快排:时间复杂度O(logn),空间复杂度O(logn)。
#include <stdio.h>
void sort_Quick(int a[],int first,int last){ //快排
int i, j, pivot, temp;
if(first<last){
pivot=first; //将第一个元素作为枢纽
i=first;
j=last;
while(i<j){ //当i和j不等
while(a[i]<=a[pivot]&&i<last) //从左到右,找到比枢纽元素大的
i++;
while(a[j]>a[pivot]) //从右往左,找到比枢纽元素小的
j--;
if(i<j){ //如果找到,交换位置
temp=a[i];
a[i]=a[j];
a[j]=temp;
} //继续找,直到i和j相遇,即左边都比枢轴元素小,右边都比数轴大
}
temp=a[pivot]; //数轴元素与j交换,到达正确位置
a[pivot]=a[j];
a[j]=temp;
sort_Quick(a,first,j-1); //递归左数组
sort_Quick(a,j+1,last); //递归右数组
}
}
int main(){
int i;
int list[]={92,3,45,99,37,49,14,58,81,21};
sort_Quick(list,0,10-1);
for(i=0;i<10;i++)
printf("%d ",list[i]);
return 0;
}
归并:时间复杂度O(logn),空间复杂度O(n)。
#include <stdio.h>
// 归并函数,实现将两个有序的子数组合并为一个有序数组
void merge(int arr[], int tmp[], int left, int mid, int right) {
int i = left, j = mid, k = left; // 分别用三个指针指向左右两个子数组和临时数组的起始位置
while (i < mid && j <= right) { // 只要左右两个子数组都还有元素,就继续比较大小并合并
if (arr[i] < arr[j]) { // 如果左边的元素更小,将它放入临时数组中
tmp[k++] = arr[i++];
} else { // 如果右边的元素更小,将它放入临时数组中
tmp[k++] = arr[j++];
}
}
while (i < mid) { // 将左边剩余的元素依次放入临时数组中
tmp[k++] = arr[i++];
}
while (j <= right) { // 将右边剩余的元素依次放入临时数组中
tmp[k++] = arr[j++];
}
for (int p = left; p <= right; p++) { // 将临时数组中已经合并好的元素拷贝回原数组中
arr[p] = tmp[p];
}
}
// 归并排序辅助函数,实现归并排序的分治思想
void mSort(int arr[], int tmp[], int left, int right) {
if (left < right) { // 当待排序数组长度大于1时,继续递归拆分并合并
int mid = (left + right) / 2; // 求中间位置
mSort(arr, tmp, left, mid); // 对左半边进行递归拆分并排序
mSort(arr, tmp, mid + 1, right); // 对右半边进行递归拆分并排序
merge(arr, tmp, left, mid + 1, right); // 将左右半边合并
}
}
int main(){
int i;
int list[]={92,3,45,99,37,49,14,58,81,21};
int tmp[10];
mSort(list, tmp, 0, 10 - 1);
for(i=0;i<10;i++)
printf("%d ",list[i]);
return 0;
}