Python教程:第2章(Python进阶)2.8-2.11

2.8.四大数据结构

2.8.1.单向队列(List)

在排队的时候,我们总是从队尾开始排列,然后逐渐向前移动,直到到达第一个;随后完成任务离开队伍.这样,就构成了一个单向队列.在单向队列中,总是遵循先进先出,后进后出的原则,可以用这样一张图来演示:
单向队列
代码实现:

class mylist(object):
	def __init__(self,*args):
		self.objects=args
	def _print(self):#依次打印
		if type(self.objects)!=tuple:
			print(self.objects)
		else:
			for i in self.objects:
				print(str(i)+"	",end="")
	def _list(self):#转为列表
		if type(self.objects)!=tuple:
			return [self.objects]
		result=[]
		for i in self.objects:
			result.append(i)
		return result		
	def _add(self,new): #向队首加入元素
		result=[new]
		for i in self.objects:
			result.append(i)
		return result	
	def _pop(self):	#从队尾删除元素
		result=[]
		for i in range(len(self.objects)-1):
			result.append(self.objects[i])
		return result 
	def _isNone(self):#判断类型 为空返回0 单数据返回1 多数据返回2
		if self.objects==None:return 0
		if self.objects==[] or ():return 0
		if type(self.objects)!=tuple:return 1
		if type(self.objects)==tuple:return 2		

2.8.2.双向队列(Queue)

如果说单向队列限制高,那么双向队列就显得比较随意了.无论在队列的哪一段,都可以删除或增加.相较于单向队列,其增加了水平自由度,但仍不可以从当中增加数据.
代码实现:

class myqueue(object):
	def __init__(self,**args):
		self.objects=args
	def _print(self):#同单向队列的_print
		if type(self.objects)!=tuple:
			print(self.objects)
		else:
			for i in self.objects:
				print(str(i)+"	",end="")	
	def _list(self):#同单向队列的_list
		if type(self.objects)!=tuple:
			return [self.objects]
		result=[]
		for i in self.objects:
			result.append(i)
		return result				
	def _adds(self,new):#从队首加入
		result=[new]
		for i in self.objects:
			result.append(i)
		return result
	def _addw(self,new): #从队尾加入
		result=[]
		for i in self.objects:
			result.append(i)
		result.append(new)	
		return result
	def _delw(self):#从队尾删除
		result=[]
		for i in range(len(self.objects)-1):
			result.append(self.objects[i])
		return result  
	def _dels(self): #从队首删除
		result=[]
		for i in range(1,len(self.objects)):
			result.append(self.objects[i])
		return result	
	def _isNone(self):#同单向队列的_isNone
		if self.objects==None:return 0
		if self.objects==[] or ():return 0
		if type(self.objects)!=tuple:return 1
		if type(self.objects)==tuple:return 2

2.8.3.栈(Stack)

想象一个管子.如果我们将一个蓝球放进去,再放一个红球进去,那我们想要取出蓝球时就必须先取出红球.于是应运而生.其特点为先进后出,后进先出.
代码实现:

class mystack(object):
	def __init__(self,*args):
		self.objects=args
	def _print(self):#同前二者的_print
		if type(self.objects)!=tuple:
			print(self.objects)
		else:
			for i in self.objects:
				print(str(i)+"	",end="")	
	def _list(self):#同前二者的_list
		if type(self.objects)!=tuple:
			return [self.objects]
		result=[]
		for i in self.objects:
			result.append(i)
		return result
	def _add(self,new):#同单向队列的_add 
		result=[new]
		for i in self.objects:
			result.append(i)
		return result
	def _del(self): #同双向队列的_dels
		result=[]
		for i in range(1,len(self.objects)):
			result.append(self.objects[i])
		return result
	def _isNone(self):
		if self.objects==None:return 0
		if self.objects==[] or ():return 0
		if type(self.objects)!=tuple:return 1
		if type(self.objects)==tuple:return 2

2.8.4.链表(Link)

我们常见的list就是一种link,直接使用index进行索引,可以在任何一个位置添加或删除元素,并使用index()方法查找数据.想必各位应该都很熟悉吧?此处不再赘述.

2.9.八大基础算法

2.9.0.算法复杂度

实现一个目标所需要使用的底层步骤数(注意!不是基层!),用 O ( n ) O(n) O(n)表示.看个例子:

a=[1,2,3,...,n]
b=[]
for i in range(0,n+1):
	b.append(a[n-i-1])

b列表完全倒序了a列表.它使用了n次计算(每次将a的一个值存入b中),因此其算法复杂度为O(n)=n,第一个n没有实际意义,仅仅为了表达一个式子;而第二个n为列表a中元素的数量n.

2.9.1.穷举算法

小白最喜欢的算法,也是最最常用的算法.在数据量不大事时,直接使用for循环遍历每一个数据来寻求答案,例如:

ans=[1,2,3,4,5]
to=2
for i in range(len(ans)):
	if ans[i]==to:
		print(i)
		break

简单粗暴,简洁明了.它的算法复杂度为O(n)=n.

2.9.2.归纳(递推)算法

逐步计算得到结果.通过已知条件来一步步往后推得到结果.例如斐波那契数列:

def get(n):
	a1=a2=1
	a=[a1,a2]
	for i in range(2,n+1):
		a.append(a[i-2]+a[i-1])
	return a,a[n]	

利于调试,依次计算.算法复杂度O(n)=n-p.p为前推数(即推导一个数据需要其他数据的量).

2.9.3.递归(循环)算法

在函数中调用自己,在必要时跳出,和循环类似.同样求斐波那契数列第n项:

def get(n,a):
	if i>=2:
		result=get(n-2)+get(n-1)
	else:
		result=1
	return result		

缺点是不易于理解,算法复杂度O(n)=2n.但利于复杂函数对死循环(While True)的优化.

2.9.4.分支算法

即二叉树.在每一个节点判断一次条件,直到到达某一个无法继续向下扩展的位置.例如:

1
1.1---1.2--
1.11-1.12-1.21-1.22
1.1111.1121.1211.1221.2111.2121.2211.222

常与递归结合.每到一次分叉就判断条件,复杂度不定,但一般为 2 log ⁡ 2 n 2\log_2n 2log2n.

2.9.5.动态规划

结合树.多个枝干可能指向同一结果.同样可以与递归结合,依次判断.注意,在一些支点处,判断条件可能有重叠.这将致使它们指向相同结果.应当实时调整它们避免大量重复计算.

2.9.6.贪心算法

不从整体的最优解考虑,而是做出当前的局部最优的选择.在每一个小区块中取得满足条件的最优解,然后汇总.其本质是将求问题的整体最优解转化为一系列局部最优的选择(即贪心选择).在大数据分析中,这很有用!

2.9.7.回溯算法

在使用分支算法时,会出现多个结果的问题.如果最终只能保留一个,那么需要在某些时候从次枝叶返回/回溯到上一个节点,考虑放宽判断条件或者直接跳过(continue)某一分支.

2.9.8.模拟算法

在真正计算之前用其他判断的条件来模拟计算条件.一般而言会放宽条件.如果放宽后仍没有结果,那么可以直接跳过该分支.

2.10.本章总结

2.10.1.习题讲解

import os
import pandas
import matplotlib.pyplot as plt
os.rename("text.txt","text.csv")
df=pandas.read_csv("text.csv")
with open("result.txt","w",encoding="utf-8") as w:
	w.write(df)
plt.scatter(df)
plt.show()	

2.10.2.本章小结

本章为Python教程的第二章.通过学习错误与试错(try…except)、迭代器与可迭代对象、惰性计算、匿名函数(lambda)、数组(array)、数据表(dataframe)、上传自己的模块和包、数据可视化(matplotlib)、四大数据机构和八大基础算法,想必各位对于Python本身已经有了非常好的理解程度.
下一章,我们将一起走进数据的世界,从权重算法开始学习,我们将学到有关机器学习的内容和简单数据库(MySQL)的使用.如果有机会,我们还会一起走进真正的大数据库(Spark),徜徉在百万级数据库中,从select和App对象层层深入.
那么所有Python入门的内容到此为止了.接下来,让我们准备好,开往数据科学的列车,即将出发!

2.11.补充阅读:一些有趣的算法

2.11.1.排序的10种可能性

声明:由于博主对于此方面并不是特别熟悉,算法来自此教程.

2.11.1.1.冒泡排序

从第一个数据开始,依次比对它(a)和在它之后的数据(b).若a<b,则进入下一组比对;反之则调换a和b的位置.算法实现:

def bubble(l):
    for i in range(1, len(l)):
        for j in range(0, len(l)-i):
            if l[j] > l[j+1]:
                l[j], l[j + 1] = l[j + 1], l[j]
    return l

2.11.1.2.选择排序

不断遍历数组,依次挑出最小的数并放置在数组开头.算法实现:

def select(l):
    for i in range(len(l)-1):
        mi=i
        for j in range(i+1, len(l)):
            if arr[j] < l[mi]:
                mi = j 
        if i != mi:
            l[i],l[mi]=l[mi],l[i]
    return l

2.11.1.3.插入排序

依次遍历数组,插入到合适的位置.算法实现:

def insertionSort(arr):
    for i in range(len(arr)):
        preIndex = i-1
        current = arr[i]
        while preIndex >= 0 and arr[preIndex] > current:
            arr[preIndex+1] = arr[preIndex]
            preIndex-=1
        arr[preIndex+1] = current
    return arr

以上3种是相对实用的排序算法,如果对其他的感兴趣,也可以前往前文的网址查看.

2.11.2.KNN算法

如果要判断一个数的类型,可以根据它的邻居来推断.俗称物以类聚.KNN算法可以对一个数据组中的某一数据进行猜测.例如有列表:(为了方便展示用表格形式展示):

index012345678910
number11.11.1223?3.144.34.45
typeintfloatfloatintint?floatintfloatfloatint

现在index为5的位置类型未知,而其他位置的类型均为已知.现在我们分别取样观察:
1.取邻居数n为1.那么也就是取2n,2个邻居.它们就是index为4的int和index为6的float.显然此时两个类型数量相等.
2.取n为2,即index=3,4,6,7.类型分别为int,int,float,int.此时int比float多,可以初步判断index=5的数也为int.
3.取n为3,即index=2,3,4,6,7,8.类型包括3个int和3个float,相等.
4.取n为4,即index=1,2,3,4,6,7,8,9.类型包括3个int和5和float.float又比int多了,因此判断index=5的数也为float.
5.取n为5,即index=0,1,2,3,4,6,7,8,9,10.现在又是int和float各5个,相等.

现在告诉你答案,index=5的数是个float.这样一来,在同样的模型下邻居数n就可以放心的取4了,因为它会相对可靠.这就是KNN算法,又称取领算法.它在人工智能领域中非常非常有用.请尝试用Python实现它(给定列表).

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值