我的第十篇博客---python数据结构与算法基础知识

python数据结构与算法基础知识

数据结构是计算机( 存储、组织数据 )的方式。
(1.在现实世界中,不同数据元素之间不是独立的,而是存在特定关系的,我们将这些关系称为结构。
(2.同样在计算机中,数据元素也不是孤立、杂乱无序的,而是具有内在联系的数据集合。

按照不同的角度, ( 数据结构 ) 可分为( 逻辑结构) 和( 物理结构 )。
(1.其中( 逻辑结构 )是( 面向问题 )的
(2.而( 物理结构 )是( 面向计算机 )的
(3.他们的基本目标都是存储 ( 数据 ) 及其 ( 逻辑关系 ) 到计算机内存中

逻辑结构:
是指数据对象中数据元素之间的相互关系。分为四种:
(1、 集合结构
(2、线性结构
(3、树形结构
(4、图形结构

物理结构:
(1、物理(存储)结构:
是指数据的逻辑结构在计算机中的存储形式。
数据的存储结构应正确反映数据元素之间的逻辑关系,这是关键。
(2、数据元素的存储结构可分为两种:
( 顺序存储结构 )和( 链式存储结构 )。
(3、顺序存储结构:
把数据元素放在( 地址连续 )的存储单元中,数据间的逻辑关系和物理关系( 一致 )。如:数组
(4、链式存储结构:
把数据元素放在( 任意 )的存储单元中,数据间使用( 指针 )关联。
(5、数据元素的存储关系不能反映其逻辑关系。如,链表

算法:
算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作。
算法的基本特性:
(1、输入输出,算法具有零个或多个输入,至少有一个或多个输出。
(2、有穷性,算法在执行有限步后能够自动结束,不会出现无限循环。
(3、确定性,算法的每一步都具有确定的含义,不会出现二义性。
(4、可行性,算法的每一步都能够通过执行有限次完成操作。

算法的复杂度:
(1、 算法复杂度分为时间复杂度和空间复杂度。
(2、时间复杂度是指执行算法所需要的计算工作量。
(3、空间复杂度是指执行这个算法所需要的内存空间。

时间复杂度:
算法的时间复杂度反映了算法执行的时间长短,他是度量一个算法好坏的重要指标。
度量一个算法的时间复杂度通常采用“大O表示法”

时间复杂度的几条基本计算规则:
1、 基本操作,即只有常数项,认为其时间复杂度为O(1)
2、顺序结构,时间复杂度按加法进行
3、循环结构,时间复杂度按乘法进行计算
4、分支结构,时间复杂度取最大值
5、判断一个算法的效率时,往往只需要关注操作数量的最高次项,其他次要项和常数项可以忽略
6、在没有特殊说明时,我们所分析的算法的时间复杂度都是指最坏时间复杂度

例如:
for i in range(n):
print(i) 时间复杂度为O(n)

for i in range(n):
for j in range(n):
print(i) 时间复杂度为O(n*n)

————————————————————————————————————————————————

链表:

链表失去了顺序表随机读取的优点,同时链表由于增加了节点的指针域,空间开销比较大,但对存储空间的使用要相对灵活。
链表与顺序表的各种操作复杂度如下所示:

操作 链表 顺序表
访问元素 O(n) O(1)
在头部插入/删除 O(1) O(n)
在尾部插入/删除 O(n) O(1)
在中间插入/删除 O(n) O(n)

注意:
虽然“在中间插入/删除”表面看起来复杂度都是O(n),但是链表和顺序表在插入和删除时进行的是完全不同的操作。链表的主要耗时操作是遍历查找,删除和插入操作本身的复杂度是O(1).顺序表查找很快,主要耗时的操作是拷贝覆盖。因为除了目标元素在尾部的特殊情况,顺序表进行插入和删除时需要对操作点之后的所有元素进行前后移位操作,只能通过拷贝和覆盖的方法进行。

————————————————————————————————————————————————————

栈与队列的区别:
栈与队列,他们都是特殊的线性表,只是对插入和删除操作做了限制。
(1、
栈限定仅能在栈顶进行插入和删除操作,而队列限定只能在队尾插入,在队头删除。
(2、
栈:后进先出 后进来的元素先出去 只允许在栈顶进行添加和删除
队列:先进先出 先进来的元素先出去 在队尾插入,在队头删除

共同点:
他们都可以使用顺序存储结构和链式存储结构两种方式实现

——————————————————————————————————————————————————————

排序与算法复杂度:

冒泡排序:
最优时间复杂度:O(n)
表示便利一次发现没有任何可以交换的元素,排序结束
最坏时间复杂度:O(n*n)
稳定性:稳定
选择排序:
最优时间复杂度:O(n*n)
最坏时间复杂度:O(n*n)
稳定性:不稳定(考虑升序每次选择最大的情况)

Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)<…<Ο(2n)<Ο(n!)

log2n一般简写为logn
for (i=1; i<=n; i++)
  x++;

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

  第一个for循环的时间复杂度为Ο(n),第二个for循环的时间复杂度为Ο(n2),则整个算法的时间复杂度为Ο(n+n2)=Ο(n2)。

————————————————————————————————————————————————————

链表代码:

游标循环一次自动是下一个的值,跟next()差不多
例如

节点包含元素域和链接域

创建一个游标,指向头结点:
cur=self.__head
当游标指向位置不为空时:
while cur is not None: #这里的cur意思是节点,若是cur.next代表的则是链接域里的值 ,
print(cur.item)
移动游标
cur=cur.next #这里cur.next代表的意思是下一个节点,也就是cur=下一个节点

cur.item代表的是元素域 也就是元素值
cur.next代表的是链接域 也就是下一个元素值的地址 最后一个指向None

这里就是cur.next的用法

def append(self, item):
'''链表尾部添加元素'''
# 创建新节点对象,将数据存储到新节点中
node = Node(item)
# 判断链表是否为空
if self.is_empty():
# 头部添加--将头结点指向node节点
self.__head = node
else:
# 创建出cur游标,找到尾节点
cur = self.__head
# 移动游标,游标指向位置不为空时
while cur.next is not None:
# 移动游标
cur = cur.next
# 当循环结束之后,cur指向尾节点,此时将新的尾节点添加到旧的尾节点之后
cur.next = node

猜你喜欢

转载自www.cnblogs.com/sll-csdn/p/10809668.html