内容:

1.数组

2.链表

3.字典

4.二叉树(搜索树)

5.set集合实现

1.数组

数组在python中是以列表的形式存在,基本上每一个语言中都有数组形式的数据结构存在

数组一般存储在连续的一块内存,数组存取元素时间是 O(1),插入、删除是 O(n),另外可以用数组实现栈和队列,栈:先进后出,队列:先进先出

另外python list中有两个部件:

  • 数组 存储数据在链表中的地址
  • 链表 实际存储数据

列表:

 lt = [1, 2, 3, 4, 5, 5]

 # 存取
print(lt[0])
lt[1] = 666
print(lt) # 插入元素
lt.insert(0, 333)
print(lt) # 删除元素
# 按值删除:
lt.remove(5)
print(lt)
# 按索引删除:
lt.pop(0)
print(lt)
del lt[0]
print(lt)

用python中的list相关操作实现栈和列表如下:

 # encoding: utf-8
# __author__ = "wyb"
# date: 2018/9/28 class Stack(object):
def __init__(self):
self.lt = [] def empty(self):
"""
判断栈是否为空
:return:
"""
return len(self.lt) == 0 def top(self):
"""
查看栈顶的对象,但不移除
:return:
"""
if not self.empty():
return self.lt[-1]
return None def push(self, obj):
"""
把对象压入栈顶
:return:
"""
self.lt.append(obj) def pop(self):
"""
移除栈顶对象,并返回该对象的值
:return:
"""
if not self.empty():
return self.lt.pop()
return None def search(self, obj):
"""
返回对象在栈中的位置,以1为基数
:param obj:
:return:
"""
if not self.empty():
return self.lt.index(obj) + 1
return -1 class Queue(object):
def __init__(self):
self.lt = [] def empty(self):
"""
判断队列是否为空
:return:
"""
return len(self.lt) == 0 def first(self):
"""
查看队首的对象,但不移除
:return:
"""
if not self.empty():
return self.lt[0]
return None def enqueue(self, obj):
"""
将指定元素加入队列的尾部
:param obj:
:return:
"""
self.lt.append(obj) def dequeue(self):
"""
移除队首对象,并返回该对象的值
:return:
"""
if not self.empty():
return self.lt.pop(0)
return None def search(self, obj):
"""
返回对象在队列中的位置,以1为基数
:param obj:
:return:
"""
if not self.empty():
return self.lt.index(obj) + 1
return -1

用python list实现python中的set:

 # encoding: utf-8
# __author__ = "wyb"
# date: 2018/9/29 class Set(object):
def __init__(self, *args):
self.table_size = 10007
self.data = [0] * self.table_size
for i in args:
self.add(i) def __repr__(self):
"""
调用str及输出的魔法方法
:return:
"""
lt = set()
for i in range(0, len(self.data)):
if self.data[i] != 0:
item = self.data[i]
lt.add(item[0])
return str(lt) def __eq__(self, other):
"""
判断相等的魔法方法
:param other:
:return:
"""
if type(other) == type(self):
return str(self.data) == str(other.data)
else:
return False def remove(self, x):
index = self._index(x)
self.data[index] = 0 def _index(self, obj):
index = hash(obj) % self.table_size
return index def _insert_at_index(self, index, key):
v = self.data[index]
if v == 0:
self.data[index] = [key]
else:
return False def add(self, key):
# 先计算出下标
index = self._index(key)
# 在下标处插入元素
self._insert_at_index(index, key) # for i in range(0, len(self.data)):
# if self.data[i] == x:
# return False
# self.data.append(x) def has(self, key):
index = self._index(key)
# 取元素
v = self.data[index]
if isinstance(v, list):
if v[0] == key:
return True
return False # for i in range(0, len(self.data)):
# if self.data[i] == x:
# return True
# return False def testSet():
a = Set(1, 2, 2, 3, 4, 4)
b = Set(1, 2, 2, 3, 4)
c = Set(1, 3, 4, 2)
d = Set(2, 3)
assert (str(a) == '{1, 2, 3, 4}')
print(a, b, c, d)
assert (a == b)
assert (a == c)
assert (a != d)
assert (a.has(1) is True)
a.remove(1)
assert (a.has(1) is False)
a.add(1)
assert (a.has(1) is True) if __name__ == '__main__':
testSet()

2.链表

我们可以将链表比作手拉手的盒子,一个盒子只能访问左右手的盒子

以下标方式读取元素的时间是 O(n),插入、删除是 O(1),栈和队列可以用链表实现,栈:先进后出,队列:先进先出

链表简单实现:

 # encoding: utf-8
# __author__ = "wyb"
# date: 2018/9/27 class Node():
def __init__(self, element=None):
self.e = element
self.next = None def append(node, element):
"""
append: 添加一个元素到末尾
:param node: 是一个 Node 实例
:param element: 任意类型的元素
"""
n = node
while n.next is not None:
n = n.next
# n 现在是最后一个元素
new_node = Node(element)
n.next = new_node def prepend(head_node, element):
"""
prepend: 添加一个元素到开头
:param head_node: 头元素
:param element: 任意类型的元素
:return:
"""
n = Node(element)
n.next = head_node.next
head_node.next = n def pop(head_node):
"""
pop是stack的两个操作之一
push 入栈
pop 出栈
prepend + pop 就实现了 队列 的 入队(enqueue)和出队(dequeue)操作
append + pop 就实现了 栈 的 入栈(push) 和 出栈(pop)操作
:param head_node: 头部节点
:return:
"""
tail = head_node
while tail.next is not None:
tail = tail.next
# 现在 tail 是最后一个元素了
n = head_node
while n.next is not tail:
n = n.next
# 现在 n 是 tail 之前的元素了
n.next = None
return tail.e def log_list(node):
n = node
s = ''
while n is not None:
s += (str(n.e) + ' > ')
n = n.next
print(s[0: -2]) head = Node()
n1 = Node(111)
n2 = Node(222)
n3 = Node(333)
n1.next = n2
n2.next = n3 head.next = n1 log_list(n1)
append(n1, 'gua')
log_list(n1)
prepend(head, 'hello')
log_list(head)
print('pop head: ', pop(head))
log_list(head)

链表封装成类:

 # encoding: utf-8
# __author__ = "wyb"
# date: 2018/9/27 # 节点类
class Node(object):
def __init__(self, element=-1):
self.element = element
self.next = None # 链表类
class LinkedList(object):
def __init__(self):
self.head = None def is_empty(self):
"""
判断链表是否为空
:return:
"""
return self.head is None def length(self):
"""
获得链表长度(包含head)
:return:
"""
index = 0
node = self.head
while node is not None:
index += 1
node = node.next
return index def find(self, element):
"""
查找元素
:param element: 元素值
:return:
"""
node = self.head
while node is not None:
if node.element == element:
return node
node = node.next
return None def _node_at_index(self, index):
"""
返回某个节点
:param index: 索引 -> 从0开始 0是head
:return:
"""
i = 0
node = self.head
while node is not None:
if i == index:
return node
node = node.next
i += 1
return None def element_at_index(self, index):
"""
返回某个节点的值
:param index: 索引 -> 从0开始 0是head
:return:
"""
node = self._node_at_index(index)
return node.element def first_object(self):
"""
返回第一个节点 -> head
:return:
"""
return self._node_at_index(0) def last_object(self):
"""
返回最后一个节点
:return:
"""
i = 0
while self._node_at_index(i) is not None:
i += 1
return self._node_at_index(i - 1) def insert_before_index(self, position, element):
"""
在节点之前插入元素
:param position: 节点位置
:param element: 元素值
:return:
"""
insert_node = Node(element)
# 错误情况判断:
if position == 0:
print("不能在head之前插入元素")
return False
if self._node_at_index(position) is None:
print("节点顺序超了!请输入正确的节点顺序!")
return False
node = self._node_at_index(position - 1)
# 插入元素
insert_node.next = node.next
node.next = insert_node def insert_after_index(self, position, element):
"""
在节点之后插入元素
:param position: 节点位置
:param element: 元素值
:return:
"""
insert_node = Node(element)
node = self._node_at_index(position)
# 错误情况判断:
if node is None:
print("节点顺序超了!请输入正确的节点顺序!")
return False
# 在节点之后插入元素
insert_node.next = node.next
node.next = insert_node def append(self, element):
"""
在最后插入节点
:param element: 节点值
:return:
"""
node = Node(element)
if self.head is None:
self.head.next = node
else:
last_node = self.last_object()
last_node.next = node
node.front = last_node def prepend(self, element):
"""
在开头插入节点
:param element: 节点值
:return:
"""
node = Node(element)
node.next = self.head.next
self.head.next = node def pop(self):
"""
删除最后一个节点
:return:
"""
tail = self.first_object()
while tail.next is not None:
tail = tail.next
# 现在 tail 是最后一个元素了
n = self.first_object()
while n.next is not tail:
n = n.next
# 现在 n 是 tail 之前的元素了
n.next = None
return tail.element def log_list(self, msg=""):
"""
输出链表
:param msg: 输出链表之前显示的信息
:return:
"""
n = self.head.next
s = msg + ''
while n is not None:
s += (str(n.element) + ' > ')
n = n.next
print(s[0: -2]) # 测试链表初始化及输出链表:
def test_log():
head = Node(0)
n1 = Node(1)
n2 = Node(2)
n3 = Node(3)
lt = LinkedList()
lt.head = head
head.next = n1
n1.next = n2
n2.next = n3
lt.log_list("输出链表: ")
return lt # 测试链表判空及链表长度:
def test_empty_length(lt):
if lt.is_empty() is True:
print("链表为空")
return None
else:
length = lt.length()
print("链表不为空, 链表长度为: ", length)
return length # 测试find
def test_find(lt):
if lt.find(5) is None:
print("链表中不存在5")
else:
print("链表中存在5")
node = lt.find(5)
return node if lt.find(3) is None:
print("链表中不存在3")
else:
print("链表中存在3")
node = lt.find(3)
return node # 测试element_at_index
def test_element_at_index(lt):
print(lt.element_at_index(0))
print(lt.element_at_index(1))
print(lt.element_at_index(2))
print(lt.element_at_index(3)) # 测试first_obj和last_obj
def test_first_last(lt):
print(lt.first_object().element)
print(lt.last_object().element) # 测试插入
def test_insert(lt):
lt.insert_before_index(0, "在节点0之前插入")
lt.log_list()
lt.insert_before_index(1, "在节点1之前插入")
lt.log_list()
lt.insert_after_index(0, "在节点0之后插入")
lt.log_list()
lt.insert_after_index(2, "在节点2之后插入")
lt.log_list()
lt.append("在最后插入节点")
lt.log_list()
lt.prepend("在开头插入节点")
lt.log_list() # 测试pop
def test_pop(lt):
lt.pop()
lt.log_list("删除最后一个元素: ") # 单元测试
def test():
linked_list = test_log() # 测试空链表:
# test_empty_length(LinkedList()) # 测试非空链表:
# test_empty_length(linked_list) # 测试find
# test_find(linked_list) # 测试element_at_index
# test_element_at_index(linked_list) # 测试first_obj和last_obj
# test_first_last(linked_list) # 测试insert
# test_insert(linked_list) # 测试pop
# test_pop(linked_list) if __name__ == '__main__':
test()

另外,关于栈和队列的实现:

上述链表实现中prepend + pop 就实现了 队列 的 入队(enqueue)和出队(dequeue)操作,append + pop 就实现了 栈 的 入栈(push) 和 出栈(pop)操作

 # encoding: utf-8
# __author__ = "wyb"
# date: 2018/9/28 """
数据结构的核心是,一个结构只有特定的操作,可以实现特定的功能 栈的特点是「先进后出」,一般有这几个操作
# push 将一个元素存入栈中
# pop 将一个元素从栈中取出,并在栈中删除它 # top 将一个元素从栈中取出
# is_empty 查看栈是否是空的 """ # Node类是一个节点,有两个属性,一个存储元素,一个存储指向另一个节点的引用
class Node:
def __init__(self, element=None, next=None):
self.element = element
self.next = next # 这个函数是会在print的时候被自动调用,就是把这个Node显示出来
def __repr__(self):
return str(self.element) class Stack:
# 初始化函数,自动被调用
# 初始化Stack()类的时候,它有一个head属性,值是一个空的Node
def __init__(self):
self.head = Node() # 如果head的next属性为空,则说明栈是空的
def is_empty(self):
return self.head.next is None # 创建一个node,并让它指向当前head.next指向的元素,再把head.next指向它
def push(self, element):
self.head.next = Node(element, self.head.next) # 取出head.next指向的元素,如果栈不是空的,就让head.next指向node.next,这样node就不在栈中了
def pop(self):
node = self.head.next
if not self.is_empty():
self.head.next = node.next
return node # head.next就是栈里面第一个元素
def top(self):
return self.head.next # 测试函数
def test():
s = Stack() s.push(1)
s.push(2)
s.push(3)
s.push(4) print(s.pop())
print(s.pop())
print(s.pop())
print(s.pop()) if __name__ == '__main__':
# 运行测试函数
test()

链表实现栈

 # encoding: utf-8
# __author__ = "wyb"
# date: 2018/9/28 """
队列的特点是「先进先出」,一般有这几个操作 # enqueue 将一个元素存入队列中
# dequeue 将一个元素从队列中取出,并在队列中删除它 # empty 查看栈是否是空的 可以把队列看做排队,银行叫号机就是队列,先取号的先入队,叫号的时候也就先出队
""" # Node类是一个节点,有两个属性,一个存储元素,一个存储指向另一个节点的引用
class Node:
def __init__(self, element=None, next=None):
self.element = element
self.next = next # 这个函数是会在print的时候被自动调用,就是把这个Node显示出来
def __repr__(self):
return str(self.element) class Queue:
# 初始化函数,自动被调用
# 初始化Queue()类的时候,它有2个属性,分别指向头尾
def __init__(self):
self.head = Node()
self.tail = self.head # 如果head的next属性为空,则说明队列是空的
def empty(self):
return self.head.next is None # 创建一个node
# 让tail.next指向它
# 让tail指向它,tail现在就是新的队尾了
def enqueue(self, element):
n = Node(element)
self.tail.next = n
self.tail = n # 取出head.next指向的元素,如果队列不是空的,就让head.next指向node.next,这样node就不在队列中了
def dequeue(self):
node = self.head.next
if not self.empty():
self.head.next = node.next
return node # 测试函数
def test():
q = Queue() q.enqueue(1)
q.enqueue(2)
q.enqueue(3)
q.enqueue(4) print(q.dequeue())
print(q.dequeue())
print(q.dequeue())
print(q.dequeue()) if __name__ == '__main__':
# 运行测试函数
test()

链表实现队列

3.字典(哈希表、对象、Map)

python中的字典把字符串转为数字作为下标存储到数组中,字符串转化为数字的算法是 O(1),所以字典的存取操作都是 O(1)

除非对数据有顺序要求,否则字典永远是最佳选择

字符串转化为数字的算法:

  • 确定数据规模,这样可以确定容器数组的大小 Size
  • 把字符当作 N 进制数字得到结果
  • eg:'gua' 被视为 g * 1 + u * 10 + a * 100 得到结果 n,n % Size 作为字符串在数组中的下标(通常 Size 会选一个 素数)
  • 当下标冲突时,有标准的解决碰撞方法(链接法)

实现字典(哈希表):

 class HashTable(object):
def __init__(self):
# table 是用来存储数据的数组
# 先让它有 10007 个格子好了
# 上课的时候说过, 这个尺寸最好选素数
# 这样可以得到更为合理的下标分布
self.table_size = 10007
self.table = [0] * self.table_size # 这个魔法方法是用来实现 in not in 语法的
def __contains__(self, item):
return self.has_key(item) def has_key(self, key):
"""
检查一个 key 是否存在, 时间很短, 是 O(1)
如果用 list 来存储, 需要遍历, 时间是 O(n)
"""
index = self._index(key)
# 取元素
v = self.table[index]
if isinstance(v, list):
# 检查是否包含我们要找的 key
for kv in v:
if kv[0] == key:
return True
# 如果得到的是 int 0 说明没找到, 返回 False
# 如果得到的是 list 但是遍历结果没有我们要找的 key 也是没找到
return False def _insert_at_index(self, index, key, value):
# 检查下标处是否是第一次插入数据
v = self.table[index]
data = [key, value]
# 也可以用这个判断 if v == 0:
if isinstance(v, int):
# 如果是第一次, 得到的是 int 0
# 那么就插入一个 list 来存, 以后相同 key 的元素都放这里面
# 注意我们把 key value 作为一个数组保存进去了, 这是因为
# 会出现相同 hash 值的 key
# 这时候就需要比较原始信息来找到相应的数据
self.table[index] = [data]
else:
# 如果不是, 得到的会是 list, 直接 append
self.table[index].append(data) def add(self, key, value):
"""
add 函数往 hashtable 中加入一对元素
我们先只支持字符串当 key
"""
# 先计算出下标
index = self._index(key)
# 在下标处插入元素
self._insert_at_index(index, key, value) def get(self, key, default_value=None):
"""
这个和 dict 的 get 函数一样
"""
index = self._index(key)
# 取元素
v = self.table[index]
if isinstance(v, list):
# 检查是否包含我们要找的 key
for kv in v:
if kv[0] == key:
return kv[1]
# 如果得到的是 int 0 说明没找到, 返回 default_value
# 如果得到的是 list 但是遍历结果没有我们要找的 key 也是没找到
return default_value def _index(self, key):
# 先计算出下标
return self._hash(key) % self.table_size def _hash(self, s):
"""
下划线开始的函数被我们视为私有函数
但实际上还是可以在外部调用, 这只是一个给自己看的标记
"""
n = 1
f = 1
for i in s:
n += ord(i) * f
f *= 10
return n def test():
import uuid
names = [
'gua',
'xiao',
'name',
'web',
'python',
]
ht = HashTable()
for key in names:
value = uuid.uuid4()
ht.add(key, value)
print('add 元素', key, value)
for key in names:
v = ht.get(key)
print('get 元素', key, v)
print('魔法方法', 'gua' in ht) if __name__ == '__main__':
test()

4.二叉树(搜索树)

二叉树(又叫搜索树):

 # encoding: utf-8
# __author__ = "wyb"
# date: 2018/9/28 class Tree(object):
def __init__(self, element=None):
self.element = element
self.left = None
self.right = None def traversal(self):
"""
树的遍历, 是一个递归操作
"""
print(self.element) # 前序遍历
if self.left is not None:
self.left.traversal()
# print(self.element) # 中序遍历
if self.right is not None:
self.right.traversal()
# print(self.element) # 后序遍历 def reverse(self):
"""
翻转二叉树
:return:
"""
self.left, self.right = self.right, self.left
if self.left is not None:
self.left.reverse()
if self.right is not None:
self.right.reverse() def test():
# 手动构建二叉树
t = Tree(0)
left = Tree(1)
right = Tree(2)
t.left = left
t.right = right
# 遍历
t.traversal() if __name__ == '__main__':
test()

5.set集合实现

(1)题目要求

 # 作业一:
# 写一个 set 的类, 无序且元素不重复,内部使用数组来存储元素,具有以下成员函数
# 1. remove ,删除元素
# 2. add, 增加元素
# 3. has,判断元素是否存在
# 形式如下:
# class Set(object):
# def __init__(self, *args)
# self.data = []
# # ...
# def remove(self, x):
# pass
# def add(self, x):
# pass
# def has(self, x):
# pass
#
#
# 作业二:
# 在作业一的基础上,在Set类里增加 __repr__ 和 __eq__ 两个成员函数。
# 并通过附带 testSet() 函数的测试。
# 形式如下:
# class Set(object):
# # ...
# def __init__(self, *args)
# self.data = []
#
# def __repr__(self):
# pass
#
# def __eq__(self, other):
# pass
#
# def remove(self, x):
# pass
# def add(self, x):
# pass
# def has(self, x):
# pass
#
# def testSet():
# a = Set(1, 2, 2, 3, 4, 4)
# b = Set(1, 2, 2, 3, 4)
# c = Set(1, 3, 4, 2)
# d = Set(2, 3)
# assert (str(a) == '{1, 2, 3, 4}')
# print(a, b, c, d)
# assert (a == b)
# assert (a == c)
# assert (a != d)
# assert (a.has(1) == True)
# a.remove(1)
# assert (a.has(1) == False)
# a.add(1)
# assert (a.has(1) == True)
#
#
# 作业三:
# 参考第17课板书 hash_table 的代码,写一个类 Set,实现时间复杂度为O(1) 的 add,remove 函数 。
# 形式如下:
# class Set(object):
# # ...
# def add(self, x):
# pass
#
# def remove(self, x):
# pass

(2)实现

python拓展4 数据结构的更多相关文章

  1. Python 中的数据结构总结(一)

    Python 中的数据结构 “数据结构”这个词大家肯定都不陌生,高级程序语言有两个核心,一个是算法,另一个就是数据结构.不管是c语言系列中的数组.链表.树和图,还是java中的各种map,随便抽出一个 ...

  2. python 下的数据结构与算法---8:哈希一下【dict与set的实现】

    少年,不知道你好记不记得第三篇文章讲python内建数据结构的方法及其时间复杂度时里面关于dict与set的时间复杂度[为何访问元素为O(1)]原理我说后面讲吗?其实就是这篇文章讲啦. 目录: 一:H ...

  3. Python算法与数据结构--求所有子数组的和的最大值

    Python算法与数据结构--求所有子数组的和的最大值 玄魂工作室-玄魂 玄魂工作室秘书 玄魂工作室 昨天 题目:输入一个整形数组,数组里有正数也有负数.数组中连续的一个或多个整数组成一个子数组,每个 ...

  4. Python中的数据结构

    Python中的数据结构 这里总结一下Python中的内置数据结构(Built-in Data Structure):列表list.元组tuple.字典dict.集合set,涵盖的仅有部分重点,详细地 ...

  5. 用Python实现的数据结构与算法:开篇

    一.概述 用Python实现的数据结构与算法 涵盖了常用的数据结构与算法(全部由Python语言实现),是 Problem Solving with Algorithms and Data Struc ...

  6. linux和windows下安装python拓展包及requirement.txt安装类库

    python拓展包安装 直接安装拓展包默认路径: Unix(Linux)默认路径:/usr/local/lib/pythonX.Y/site-packagesWindows默认路径:C:\Python ...

  7. Python 下的数据结构实现

    既然采用了 Python 编程语言实现数据结构,就要充分发挥 Python 语言的语法特性. 参考<Python 算法教程><数据结构与算法 -- Python 语言描述>: ...

  8. Python入门篇-数据结构堆排序Heap Sort

    Python入门篇-数据结构堆排序Heap Sort 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.堆Heap 堆是一个完全二叉树 每个非叶子结点都要大于或者等于其左右孩子结点 ...

  9. Python入门篇-数据结构树(tree)的遍历

    Python入门篇-数据结构树(tree)的遍历 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.遍历 迭代所有元素一遍. 二.树的遍历 对树中所有元素不重复地访问一遍,也称作扫 ...

随机推荐

  1. rar ubuntu

    http://jingyan.baidu.com/article/1612d5004095eee20e1eeeab.html sudo 7z x ***.rar

  2. FREESWITCH 填坑指南

    转接 1.查看网关注册状态 sofia status 2.桥接(未实践) http://wiki.freeswitch.org.cn/wiki/Mod_lua.html#jump10237 frees ...

  3. 【计算机视觉】如何使用于仕琪老师的libfacedetect人脸检测库

    前言 最近又开始进行人脸检测方向的内容,看到于仕琪老师的多角度检测想试一下,还不清楚原理,先测试效果如何. libfacedetect人脸检测库是深圳大学于仕琪老师发布的开源库,与opencv自带的人 ...

  4. 【error】select timeout问题

    使用摄像头的过程中出现这个问题,说明是找不到摄像头了, 有可能是摄像头驱动问题,也有可能是摄像头接口处接触不良等原因造成的. re 1.select-timeout-opencv; End

  5. CentOS 7关闭图形桌面开启文本界面

    1,命令模式systemctl set-default multi-user.target 2,图形模式systemctl set-default graphical.target CentOS 7 ...

  6. java导出Excel 好文收藏

    http://www.cnblogs.com/Damon-Luo/p/5919656.html https://www.cnblogs.com/klguang/p/6425422.html

  7. LeetCode Single Number I II Python

    Single Number Given an array of integers, every element appears twice except for one. Find that sing ...

  8. vulcanjs 开源工具方便快速开发react graphql meteor 应用

    vulcan 开源工具方便快速开发react graphql meteor 应用 操作环境mac os 安装 meteor 安装(此安装有点慢,可以通过正确上网解决) curl https://ins ...

  9. BAT 批处理脚本教程

    第一章 批处理基础第一节 常用批处理内部命令简介 批处理定义:顾名思义,批处理文件是将一系列命令按一定的顺序集合为一个可执行的文本文件,其扩展名为BAT或者CMD.这些命令统称批处理命令.小知识:可以 ...

  10. 防范SQL注入漏洞攻击

    原理:通过拼sql语句,在输入框里输入' ; SHOW TABLES;注入这样的代码, 防范:你把全部的特殊符号都过滤掉(如单引号,双引号),自然就不会被注入 使用mysql_real_escape_ ...