数据结构与算法笔记一

来源:互联网 发布:无法登录mysql服务器 编辑:程序博客网 时间:2024/05/22 10:49

1.写个程序计算 1+2+3 +。。+100,你会怎么写?

很明显是个等差数列



所以直接用 n*(n+1)/2来实现,避免循环,在数据量特别大的时候,效果比较高,有点比较明显。

2.算法时间复杂度

算法的时间复杂度,也就是算法的时间量度,记作:t(n)=0(f(n)). o(1)代表常数阶,o(n)代表线性阶,

o(n^2)代表平方阶。具体推导时间复杂度的方法:

1.用常数1取代运行时间中的所有加法常数。

2.在修改后的运行次数函数中,只保留最高阶项。

3.如果最高阶项存在且不是1,则去除与这个项相乘的常数。

比如一个for循环1-n,复杂度就是o(n),两个for循环嵌套1-n,复杂度就是o(n^2)。两个for循环一个循环1-n,另外一个循环1-m,两个循环嵌套,时间复杂度就是o(n*m)

再比如:

int count=1;

while(count < n)

{

  count = count * 2;

}

由于每次count*2以后,就距离n更近了一分,也就是说,有多少个2相乘后大于n,则会退出循环。

由2^x=n,得到x=log2N,所以这个循环的时间复杂度为 o(logn)

再比如:

int i,j ;

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

         for(j = i; j < n; j ++)

     {

         .//do something

     }

由于当i=0的时候,内循环执行了n次,当i=1的时候,执行了n-1次,。。。当i=n-1的时候,执行了一次。所以总的执行次数为:

n + (n-1) + (n-2) + .. + 1 = n(n+1)/2 = n^2/2 + n/2,用我们的推导方法,第一条加法常数不予考虑,第二条保留最高阶项,所以保留  n^2/2,第三条去掉最高阶项的常数,所以变成 o(n^2)

再比如一个稍微特殊一点的:




常用时间复杂度举例:



3.算法空间复杂度

    算法的空间复杂度通过计算算法所需的存储空间实现,算法空间复杂度的计算公式记作:s(n)=o(f(n)),其中n为问题的规模,f(n)为语句关于n所占存储空间的函数。

当一个算法的空间复杂度为一个常量,即不随被处理数据量n的大小而改变时,可表示为O(1);当一个算法的空间复杂度与以2为底的n的对数成正比时,可表示为0(10g2n);当一个算法的空I司复杂度与n成线性比例关系时,可表示为0(n).若形参为数组,则只需要为它分配一个存储由实参传送来的一个地址指针的空间,即一个机器字长空间;若形参为引用方式,则也只需要为其分配存储一个地址的空间,用它来存储对应实参变量的地址,以便由系统自动引用实参变量。


4.线性表

线性表的优点和缺点:



比如java中 ArrayList就是线性数组实现的线性表,数组进行扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量的增长大约是其原容量的1.5倍。这种操作的代价是很高的,因此在实际使用时,我们应该尽量避免数组容量的扩张。当我们可预知要保存的元素的多少时,要在构造ArrayList实例时,就指定其容量,以避免数组扩容的发生。或者根据实际需求,通过调用ensureCapacity方法来手动增加ArrayList实例的容量。

关于ArrayList和Vector区别如下:

  • ArrayList在内存不够时默认是扩展50% + 1个,Vector是默认扩展1倍。
  • Vector提供indexOf(obj, start)接口,ArrayList没有。
  • Vector属于线程安全级别的,但是大多数情况下不使用Vector,因为线程安全需要更大的系统开销。
5.链表
   头结点的数据域可以不存储任何信息,谁叫他是第一个呢,有这个特权,也可以存储如表的长度等附加信息,头结点的指针域存储指向第一个结点的指针,如下图:

若线性表为空表,则头结点的指针域为空,即:

每个结点除了存储指向下个结点的指针外,还存储本节点存储的数据,即指针域和数据域:


链表头指针和头结点的区别:


单链表的整表删除:


6.线性表和链表的优缺点比较:



7.循环链表
   其实循环链表和单链表的主要差异就在于循环的判断条件上,原来判断p->next是否为空,现在判断p_next不等于头结点,则循环未结束。单链表中,o(1)访问第一个结点,但最后一个结点访问需要o(n)时间,有了循环链表则可以o(1)访问最后的尾结点。



有了尾指针,如果之前合并两个单链表,特别方便,效率提高:




8.双向链表

直接说循环双向链表,结构图如下:





有了循环双向链表,你可以通过任何一个结点访问他的前驱结点和后继结点,而单链表只能获取后继结点,要想获得前驱结点,需要再次循环。显然,循环双向链表这种场景更方便。

9.栈

①线性栈

栈是限定仅在表尾进行插入和删除操作的线性表。我们把允许插入和删除的一端成为栈顶,另一端

称为栈底,不含任何数据元素的栈为空栈。栈又称为后进先出的线性表,简称LIFO结构。、







我们定义一个top变量来指示栈顶元素在数组中的位置,这top就如同游标,来回移动。进栈或者出栈的时候,top移动。


②链栈

顾名思义,就是链表数据结构实现的栈。



③栈的重要应用

栈的重要应用之一,斐波那契额数列。





栈的重要应用二:

待续







0 0
原创粉丝点击