数据结构之线性结构
线性结构:
就是能用一根线串起来的数据结构
-
数组(列表)
-
问:申请数组的前提条件是啥? a[12]?内存需要满足的条件?
答:内存必须有一块连续的内存空间
-
问:int a[7] 表示什么意思
答:声明一个数组,这个数组的数组名是 a, 数组的大小是 7, 数组元素的类型是整型。 int a[7] = array(1,2,3,4,5,6,7)
-
问:如何申请内存?
答:C,C++语言,申请:mallco (28)。释放:free(28)(一个整型是4个字节,7个数就是28个连续字节的空间)
-
问:int a[7] = [1,2,3,4,5,6,7] a[3] = 4?
答:a[3] = 首地址(1000) + 索引(3) * 类型长度(4) = 1012 --- 1015
-
问:数组首地址从哪获取?
答:数组首地址保存在数组名中,例如上面的a就会在开辟空间的时候保存首地址1000
-
列表中的增(append)删(pop)改(update)查(for)
-
-
链表
数组需要一块连续的内存空间,而链表恰恰相反,他并不需要一块连续的内存空间,他通过'指针(内存地址)'将一组零散的内存块串起使用,所以申请的大内存也不有问题
#### 梁山好汉排行榜
class Hero():
def __init__(self, number=None, name=None, nickname=None, pNext=None):
#值域
self.number = number
self.name = name
self.nickname = nickname
# 指针域
self.pNext = pNext
# 添加
def add(head, hero):
#### head 节点不能动,因此需要第三方的临时变量帮助head去遍历
cur = head
while cur.pNext != None:
### 把下一个节点的内存地址付给 cur ,那此时cur就指向下一个节点
cur = cur.pNext
### 当退出上述循环的时候偶,cur就已经指向尾节点
cur.pNext = hero
def getAll(head):
cur = head
while cur.pNext != None:
cur = cur.pNext
print('编号是:%s, 名称是:%s, 外号是:%s' % (cur.number, cur.name, cur.nickname))
def delHero(head, number):
cur = head
while cur.pNext != None:
if cur.pNext.number == number:
break
cur = cur.pNext
cur.pNext = cur.pNext.pNext
head = Hero()
h1 = Hero(1,'宋江','及时雨')
# h1本质上就是一个内存地址
add(head,h1)
约瑟夫问题
设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列
# 循环链表
class Child(object):
first = None
def __init__(self, no = None, pNext = None):
self.no = no
self.pNext = pNext
def addChild(self, n=4):
cur = None
for i in range(n):
child = Child(i + 1)
if i == 0:
self.first = child
self.first.pNext = child
cur = self.first
else:
cur.pNext = child
child.pNext = self.first
cur = cur.pNext
def showChild(self):
cur = self.first
while cur.pNext != self.first:
print("小孩的编号是:%d" % cur.no)
cur = cur.pNext
print("小孩的编号是: %d" % cur.no)
def countChild(self, m, k):
tail = self.first
while tail.pNext != self.first:
tail = tail.pNext
# 出来后,已经是在first前面
# 从第几个人开始数
for i in range(k-1):
tail = tail.pNext
self.first = self.first.pNext
# 数两下,就是让first和tail移动一次
# 数三下,就是让first和tail移动两次
while tail != self.first: # 当tail == first 说明只剩一个人
for i in range(m-1):
tail = tail.pNext
self.first = self.first.pNext
self.first = self.first.pNext
tail.pNext = self.first
print("最后留在圈圈中的人是:%d" % tail.no)
c = Child()
c.addChild(4)
c.showChild()
c.countChild(3,2)
线性结构的两种应用方式之栈
栈的定义
一种可以实现“先进后出”的存储结构
栈类似于一个箱子,先放进去的书,最后才能取出来,同理,后放进去的书,先取出来
栈的分类
-
静态栈
-
静态栈的核心是数组,类似于一个连续内存的数组,我们只能操作其栈顶元素
-
-
动态栈
-
动态栈的核心是链表
-
栈的算法
栈的算法主要是压栈和出栈两种操作的算法,下面我就用代码来实现一个简单的栈。
首先要明白以下思路:
-
栈操作的是一个一个节点
-
栈本身也是一种存储的数据结构
-
栈有
初始化
、压栈
、出栈
、判空
、遍历
、清空
等主要方法
class Stack(object):
def __init__(self):
self.pTop = None
self.pBottom = None
class Node(object):
def __init__(self, data=None, pNext = None):
self.data = data
self.pNext = pNext
def push(s, new):
new.pNext = s.pTop
s.pTop = new
def pop(s):
cur = s.pTop
# while cur != s.pBottom:
# if cur.data == val:
# s.pTop = cur.pNext
# break
# cur = cur.pNext
# else:
# print('没有找到此元素')
while cur != s.pBottom:
s.pTop = cur.pNext
print("出栈的元素是: %d" % cur.data)
cur = cur.pNext
else:
print("出栈失败")
def getAll(s):
cur = s.pTop
while cur != s.pBottom:
print(cur.data)
cur = cur.pNext
def is_empty(s):
if s.pTop == s.pBottom:
return True
else:
return False
def clear(s):
if is_empty(s):
return None
p = s.pTop
q = None
while p != s.pBottom:
q = p.pNext
del p
p = q
else:
s.pBottom = s.pTop
head = Node()
s = Stack()
s.pTop = s.pBottom = head
n1 = Node(2)
push(s, n1)
n1 = Node(5)
push(s, n1)
n1 = Node(89)
push(s, n1)
print("##############遍历元素##########")
getAll(s)
# print("##############出栈元素#######")
# pop(s)
print("##############清空栈##########")
clear(s)
print("##############遍历元素##########")
getAll(s)
栈的应用
-
函数调用
-
浏览器的前进或者后退
-
表达式求值
-
内存分配
线性结构的两种应用方式之队列
队列的定义
一种可以实现“先进先出”的数据结构
队列的分类
-
链式队列
-
静态队列
链式队列的算法
class Node:
def __init__(self, value):
self.data = value
self.next = None
class Queue:
def __init__(self):
self.front = Node(None)
self.rear = self.front
def enQueue(self, element):
n = Node(element)
self.rear.next = n
self.rear = n
def deQueue(self):
if self.empty():
print('队空')
return
temp = self.front.next
self.front = self.front.next
if self.rear == temp:
self.rear = self.front
del temp
def getHead(self):
if self.empty():
print('队空')
return
return self.front.next.data
def empty(self):
return self.rear == self.front
def printQueue(self):
cur = self.front.next
while cur != None:
print(cur.data)
cur = cur.next
def length(self):
cur = self.front.next
count = 0
while cur != None:
count += 1
cur = cur.next
return count
if __name__ == '__main__':
queue = Queue()
queue.enQueue(23)
queue.enQueue(2)
queue.enQueue(4)
queue.printQueue()
queue.deQueue()
# queue.printQueue()
l = queue.length()
print("长度是: %d" % l)
queue.deQueue()
# queue.printQueue()
l = queue.length()
print("长度是: %d" % l)
queue.deQueue()
# queue.printQueue()
l = queue.length()
print("长度是: %d" % l)
队列的实际应用