查找算法
顺序查找
顺序查找一般又称为线性查找,它对顺序表和线性表都适用。对于顺序表,可以通过数组下标递增来顺序扫描每一个元素;对于链表,可以通过指针next来依次扫描元素。
下面是示例代码
//
int Search_Seq(int *data,int data_num,int key){
for(int i=0;i<data_num;i++){
if(data[i]==key)
return i;
}
return -1;
}
折半查找
折半查找又分为二分查找,它仅仅适用于有序的顺序表。
int Binary_Search(int *data,int data_num,int key){
int low=0,high=data_num-1;
int mid;
while(low<=high){
mid=(low+high)/2;
if(data[mid]==key)
return mid;
else if(data[mid]<key)
{
high=mid-1;
}
else{
low=mid;
}
}
return -1;
}
分块查找
分块查找又称之为索引顺序查找,它吸取了顺序查找和折半查找各自的优点,既有动态结构,又适用于快速查找。
分块查找的基本思想:将查找表分为若干块。块内的元素可以无序,但是快间的元素是有序的。分块查找的基本步骤是现在索引里面查找记录所在的快,可以顺序查找和折半查找;第二步是在块内顺序查找
排序算法
插入排序
插入排序是一种简单直观的排序算法,其基本思想是将一个待排序的记录按其关键字大小插入前面已经排好序的子序列,直到全部记录插入完成
直接插入排序算法
就是按照顺序对列表进行排序
时间复杂度 O ( n 2 ) O(n^{2} ) O(n2)空间复杂度 O ( 1 ) O(1) O(1)
void InsertSort(int *data,int n){
int i,j;
for(i=1;i<n;i++){
if(data[i]<data[i-1]){
int temp=data[i];
for(j=i-1;temp<data[j];j--){
data[j+1]=data[j];
}
data[j+1]=temp;
}
}
}
折半插入排序
直接插入排序每一趟都有重新遍历一遍前面的节点,并且前面的算子是有序的,这样就可以用折半插入排序,这样在一定条件下时间可以减半,待确定插入位置之后,再统一的向后移动元素
折半插入排序的空间复杂度为$O(n\log_{2}{n}) 时间复杂度 时间复杂度 时间复杂度O(n^{2} )$
void InsertSort(int *data,int n){
int i,j,low,high,mid;
for(i=1;i<n;i++){
low=0;
high=i-1;
int temp=data[i];
while (low<=high)
{
mid=(low+high)/2;
if(temp<data[mid])
high=mid-1;
else
low=mid+1;
}
for(j=i-1;j>=high+1;j--)
data[j+1]=data[j];
data[j+1]=temp;
}
}
希尔排序
希尔排序会存在一个步长,把数组平均分为若干组,把间隔某个增量组成一个子表,每个子表进行直接插入排序,当整个表中的元素呈基本有序时,再对全体记录进行一次直接插入排序
时间复杂度 O ( n 2 ) O(n^{2} ) O(n2)空间复杂度 O ( 1 ) O(1) O(1)
void ShellSort(int *data,int n){
int step,i,j;
for(step=n/2;step>0;step/=2){
for(i=step+1;i<n;i++){
if(data[i]<data[i-step]){
int temp=data[i];
for(j=i-step;j>0&&temp<data[j];j-=step){
data[j+step]=data[j];
}
data[j+step]=temp;
}
}
}
}
交换排序
冒泡排序
冒泡排序的核心思想是从前往后或者从后往前,比较相邻元素,若为逆序则交换他们,直到序列比较完
时间复杂度 O ( n 2 ) O(n^{2} ) O(n2)空间复杂度 O ( 1 ) O(1) O(1)
typedef unsigned int bool;
#define true 1
#define false 0
void BubbleSort(int *data,int n){
for(int i=0;i<n;i++){
bool flag=false;
for(int j=n-1;j>i;j--){
if(data[j]<data[j-1]){
int temp=data[j];
data[j]=data[j-1];
data[j-1]=temp;
flag=true;
}
}
if(flag==false)
return;
}
}
快速排序
快速排序的基本思想是分治,在待排序表中任取一个元素pivot作为枢轴,通过一趟排序把待排序表划分为两个独立的部分,pivot左边的部分小于pivot,pivot右边的部分所有元素都大于pivot;这个pivot放在最终位置上,然后再在两个独立的部分中分别找两个pivot,再进行上述操作。
空间复杂度 O ( log 2 n ) O(\log_{2}{n} ) O(log2n)时间复杂度 O ( n ∗ log 2 n ) O(n*\log_{2}{n} ) O(n∗log2n)
int Partition(int *data,int low,int high){
int pivot=data[low];
while(low<high){
while(low<high&&data[high]>=pivot)
--high;
data[low]=data[high];
while(low<high&&data[low]<=pivot)
++low;
data[high]=data[low];
}
data[low]=pivot;
return low;
}
void QuickSort(int *data,int low,int high){
if(low<high){
int pivotpos=Partition(data,low,high);
QuickSort(data,low,pivotpos-1);
QuickSort(data,pivotpos+1,high);
}
}
选择排序
简单选择排序
假设数组为data[n],其思想就是每一次选择一个最小的数与data[i]进行交换,每一次都会有一个元素确定最终的位置。
时间复杂度 O ( n 2 ) O(n^{2} ) O(n2)空间复杂度 O ( 1 ) O(1) O(1)
void SelectSort(int *data,int n){
for(int i=0;i<n;i++){
int min=i;
for(int j=i+1;j<n;j++){
if(data[min]>data[j])
min=j;
}
if(min!=i){
int temp=data[i];
data[i]=data[min];
data[min]=temp;
}
}
}
堆排序
堆的定义如下,n个关键字序列L[1~n]称之为堆,当且仅当该序列满足
- L ( i ) > = L ( 2 i ) L(i)>=L(2i) L(i)>=L(2i)且 L ( i ) > = L ( 2 i + 1 ) L(i)>=L(2i+1) L(i)>=L(2i+1)或者
- L ( i ) < = L ( 2 i ) L(i)<=L(2i) L(i)<=L(2i)且 L ( i ) < = L ( 2 i + 1 ) L(i)<=L(2i+1) L(i)<=L(2i+1)
可以将其视为一个完全二叉树,满足第一个条件的为大根堆,满足第二个条件的称之为小根堆。
堆排序的思路很简单,首先将存放在数组中的元素组成一个初始堆,堆顶的元素就是最大值或者最小值,取出堆顶元素之后将堆底元素放入堆顶,再进行堆排序。
空间复杂度 O ( 1 ) O(1) O(1)时间复杂度 O ( n ∗ log 2 n ) O(n*\log_{2}{n} ) O(n∗log2n)
//建立大根堆
void HeadAdjust(int *data,int k,int len){
// data[0]=data[k];
int temp=data[k];
for(int i=2*k+1;i<len;i*=2){
if(i<len-1&&data[i]<data[i+1])
i++;
if(temp>=data[i]) break;
else{
data[k]=data[i];
k=i;
}
}
data[k]=temp;
}
void BuildMaxHeap(int *data,int len){
for(int i=len/2;i>0;i--){
HeadAdjust(data,i-1,len);
}
}
void HeapSort(int *data,int len){
BuildMaxHeap(data,len);
for(int i=len-1;i>1;i--){
int temp=data[i];
data[i]=data[0];
data[0]=temp;
HeadAdjust(data,0,i-1);
}
}
归并排序和基数排序
归并排序
归并排序的基本思想是两两进行归并,然后再进行融合,这个是需要一个辅助数组的。
空间复杂度
O
(
n
)
O(n)
O(n)时间复杂度
O
(
n
∗
log
2
n
)
O(n*\log_{2}{n} )
O(n∗log2n)
#define num 8
int b[num];
void Merge(int *data,int low,int mid,int high){
int i,j,k;
for(k=low;k<=high;k++)
b[k]=data[k];
for(i=low,j=mid+1,k=i;i<=mid&&j<=high;k++){
if(b[i]<=b[j])
data[k]=b[i++];
else
data[k]=b[j++];
}
while(i<=mid) data[k++]=b[i++];
while(j<=high)data[k++]=b[j++];
}
void MergeSort(int *data,int low,int high){
if(low<high){
int mid=(low+high)/2;
MergeSort(data,low,mid);
MergeSort(data,mid+1,high);
Merge(data,low,mid,high);
}
}
基数排序
基数排序很特别,通常有两种方法,一种是按最高优先位来进行排序的,一种是最低优先位进行排序
本文详细介绍了顺序查找、折半查找、分块查找等查找算法,以及插入排序、折半插入排序、希尔排序、冒泡排序、快速排序、选择排序、堆排序、归并排序和基数排序等排序算法,展示了它们的原理、示例代码和时间复杂度分析。
264

被折叠的 条评论
为什么被折叠?



