2021-03-02

算法
数据结构中的算法,指的是数据所具备的功能
解决特定的问题的方法,是经验总结。
算法的五大特征
1.输入:在算法中可以有零个或者多个输入
 2.输出:在算法中至少有一个或者多个输出
3.有穷行:在执行有限的步骤之后,自动结束不会出现无限循环并且每一个步骤在可接受的时间内完成
 4.确定性:算法的每一个步骤都具有确定的含义,不会出现二义性
  5.可行性:算法的每一步都必须是可行的,也就是说,每一步都能够通过执行有限的次数完成
如何评价一个算法
时间复杂度:由于计算机的性能不同,无法准确的统计出一个算法所需要执行的时间。
因此我们用算法执行的次数来代表算法的执行复杂度O(公式)由于计算机使用二进制的记数系统,对数常常以2为底(即log2n,有时写作lgn)。
常见的时间复杂度
printf(“%d”)
//O(1)
复杂度为1

for(int i=0;i<n;i++)


printf(“%d”)

//O(n)

for(int i=n;i>=0;i/=2)


printf(“%d”)

//O(logn)

for(int i=0;i<n;i++)


for(int i=0;i<n;i++)

printf(“%d”)


//O(n^2)

 for(int i=0;i<n;i++)


for(int i=n;i>=0;i/=2)

printf(“%d”)


//O(n^logn)
分治法
分治法是把一个复杂的问题分成两个或更多的相同或相似的子问题,
再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,
原问题的解即子问题的解的合并。
实现分治的方法:循环、递归。
查找算法
顺序查找:
对查找的数据没有任何要求,从头到尾逐一查找,适合在小规模的数据查找中使用,相对效率低
时间复杂度O(n)
// 顺序查找
int order_search(int* arr,int len,int key)
{
for(int i=0; i<len; i++)
{
if(arr[i] == key) return i;
}
return -1;
}

二分查找:
      待查找的而数据必须是有序的,从数据的中间位置开始查找如果中间的值比key小,则继续在右边二分查找,如果比key大则在左边。
      时间复杂度O(logn)

// 排序
void sort(int* arr,int len)
{
for(int i=0;i<len-1;i++)
{
for(int j=i+1;j<len;j++)
{
if(arr[i] > arr[j]) swap(arr[i],arr[j]);
}
}
}
// 循环二分查找
int binary_search_for(int* arr,int len,int key)
{
int l = 0, r = len - 1;
while(l<=r)
{
int p = (l+r)/2;
if(arr[p] == key) return p;

	if(key < arr[p])	r = p-1;
	else				l = p+1;
}
return -1;

}
int _binary_search(int* arr,int l,int r,int key)
{
if(l > r) return -1;

int p = (l+r)/2;
if(arr[p] == key) return p;
if(key < arr[p]) 
	_binary_search(arr,l,p-1,key);
else 
	_binary_search(arr,p+1,r,key);

}
// 递归二分查找
int binary_search(int* arr,int len,int key)
{
return _binary_search(arr,0,len-1,key);
}

块查找:
      是一种对数据进行处理的思想,不是一种特定的算法
权重查找:

排序算法:
排序算法的稳定性:
在待排序的数据中如果有值相同的数据,在排序的过程中如果不会改变他们的相对顺序,则认为排序算法为稳定的。
4 2 1 0 9 4 3 8 7
a b
0 1 2 3 4 4 7 8 9
a b
ab稳定
ba不稳定
冒泡:
对数据左右进行比较,把最大的交换到最后,特点是该算法对数据的有序性敏感,在排序的过程中发现有序可以立即停止,如果待排序的数据基本有序,则冒泡排序的效率是非常高的。
时间复杂度:平均:O(n^2) 最优:O(n)
稳定性: 稳定的
// 冒泡排序
void bubble_sort(int* arr,size_t len)
{
// 标志位判断是否排序完成
bool flag = true;
for(int i=len-1; i>0 && flag; i–)
{
flag = false;
for(int j=0; j<i; j++)
{
//printf("===========\n");
if(arr[j] > arr[j+1])
{
swap(arr[j],arr[j+1]);
flag = true;
}
}
}
}

选择:
    假定最开始的位置是最小值的下标并记录该下标为min,然后与后面的数据进行比较,如果有比min位置的数据小的,则更新min为更小的数据的下标,最后如果最后min的值发生了变化,则交换min位置的数据与最开始位置的数据,虽然时间复杂度较高,但是数据交换的次数比较少,因此实际运行的速度并不慢
    选择排序是冒泡排序的一个变种,但是对数据的有序性不敏感,数据基本有序时冒泡快,数据较为混乱时选择快
    时间复杂度:O(n^2)
    稳定性:不稳定的  10 10 1

// 选择排序
void select_sort(int* arr,size_t len)
{
for(int i=0; i<len-1; i++)
{
int min = i;
for(int j=i+1; j<len; j++)
{
if(arr[j] < arr[min]) min = j;
}
if(min != i) swap(arr[min],arr[i]);
}
}

插入:
    把数据看成两部分,一部分是有序的,剩余的数据逐个插入进去,当数据全部插入完成后,整个数据就是有序的。
    适合对已排序好的数据,新增数据并排序
    时间复杂度:O(n^2)
    稳定性:稳定的

// 插入排序
void insert_sort(int* arr,size_t len)
{
for(int i=1,j=0; i<len; i++)
{
int val = arr[i];
for(j=i; j>0 && arr[j-1] > val;j–)
{
arr[j] = arr[j-1];
}
if(j != i) arr[j] = val;
}
}

快速排序:找到一个标杆,一方面从左边找比标杆值大的数据,找到后放在标杆的右边。另一方面从右面找比标杆值小的数据,
         放在标杆的左边。达到整体有序,在按照同样的方式排序左右;两边的数据。
         时间复杂度O(nlogn)
         稳定性:不稳定
void _quick_sort(int* arr,int left,int right)

{
if(left>=right) return;
// 计算标杆下标的位置
int pi=(right+left)/2;
//备份标杆的直
int pv=arr[pi];
//备份左右标杆的位置
int l=left,r=right;
while(l<r)
{
while(l<pi&&arr[l]<=arr[pi]) l++;
if(l<pi)
{
arr[pi]=arr[l];
pi=l;
}
while(r>pi&&arr[r]>=pv) r–;
if(r>pi)
{
arr[pi]=arr[r];
pi=r;
}
}
//还原标杆
arr[pi]=pv;
if(pi-left>1) _quick_sort(arr,left,pi-1);
if(right-pi>1) _quick_sort(arr,pi+1,right);
}
//快速排序
void quick_sort(int* arr,size_t len)
{
_quick_sort(arr,0,len-1);
show_arr(arr,len);
printf(":%s\n",func);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值