线性表
线性表,是由若干个数据特性相同的元素的组成有限序列。
根据实现方式的不同,可以分为顺序表和链表,顺序表依据结构的差异,可以分为一体式和分离式两种;链表可以分为单向链表、双向链表和环形链表。
本文以python编程的方式,对各种数据结构进行描述和实现。
顺序表
顺序表的结构可以分为表头和数据区两部分。
表头用于描述表的信息,表头信息通常包括表容量、已使用情况(当前表成员数量),如果是分离式结构(python中列表list为这种结构),还会包括数据区的首地址。
上图为分离式顺序表结构,表结构中3表示表长度,其中已包含两个表成员10和11,数据区的首地址为0x12,每个方块表示存储单元,根据数据类型的不同而占据不同的空间大小,具体需要参考C语言中对整形、字符和浮点等基本数据类型的大小规定。
对于python列表,用于表示列表的变量指向了顺序表的表头首地址,当执行append方法增加元素到列表尾部时,其表头首地址不变,而是改变数据区的数据(数据区首地址随着发生变化),这时只需改变表头中指向数据区的地址(0x12)即可,所以执行append方法的前后其(变量)id是不变的。
a=[1,2,3]
id(a) # 返回 45213256L
a.append(22)
id(a) # 返回 45213256L
python中的元组是典型的一体式顺序表,其结构如下:
链表
链表是由若干个节点首尾相连组成的,节点由数据区和指针域(链接区)组成,链接区用于储存下一个节点的地址,末尾节点的链接区为空(None)。
单链表:指针域只有一个后向指针;
双链表:指针域由一个后向指针和一个前向指针组成;
环形链表:链表尾部节点的后向指针指向链表头部节点,构成一个环形链表
这里以 单链表为例说明数据结构的python实现。
首先定义节点类 Node:
class Node():
def __init__(self, item):
# data
self.item = item
# probe
self.next = None
然后定义单链表类 single_table,类私有属性为链表的首节点地址 self.__head,实现链表长度(length方法)查询,是否为空(empty方法),列表的元素遍历(itersall方法),元素搜索(search方法)、任意位置插入(insert方法)和删除(remove方法,删除表中第一个指定元素)。
class single_table():
def __init__(self, node = None):
# head probe
self.__head = node
def empty(self):
return self.__head == None
def length(self):
count=0
cur=self.__head
while cur:
count += 1
cur=cur.next
return count
def itersall(self):
if self.empty():
return
cur=self.__head
while cur:
print(cur.item,' ,', end='')
cur=cur.next
print('')
def add(self, item):
node=Node(item)
if self.empty():
self.__head=node
return
node.next=self.__head
self.__head=node
def append(self, item):
node=Node(item)
cur=self.__head
if not cur:
self.add(item)
return
while cur.next:
cur=cur.next
cur.next=node
def insert(self, pos, item):
node=Node(item)
if pos <= 0:
self.add(item)
elif pos > self.length()-1:
self.append(item)
else:
cur=self.__head
while pos>1:
cur=cur.next
pos -= 1
node.next=cur.next
cur.next=node
def search(self, item):
cur=self.__head
#pos=0
while cur:
if cur.item ==item:
return True
cur=cur.next
#pos += 1
return False
def remove(self, item):
pre=self.__head
# empty
if not pre:
return
cur=pre.next
# only 1 element
if not cur:
if pre.item ==item:
self.__head = None
return
while cur:
if pre.item ==item:
if pre == self.__head:
self.__head=cur
else:
pre.next=cur.next
break
elif cur.item ==item:
if cur.next:
pre.next=cur.next
else:
pre.next=None
break
pre=pre.next
cur=pre.next
对于环形链表,这里以环形单链表为例,通过python代码实现,与上面的单链表比较,差别主要在于 首尾节点互联,实现的方法是相同的,仅做少量修改。
class Node():
def __init__(self, item):
# data
self.item = item
# probe
self.next = None
class singleCYC_table():
def __init__(self, node = None):
# head probe
self.__head = node
if node:
node.next = node
def empty(self):
return self.__head == None
def length(self):
if self.empty():
return 0
count=1
cur=self.__head
while cur.next != self.__head:
count += 1
cur=cur.next
return count
def itersall(self):
if self.empty():
return
cur=self.__head
while cur.next != self.__head:
print(cur.item,' ,', end='')
cur=cur.next
print(cur.item,' ,', end='')
print('')
def add(self, item):
node=Node(item)
if self.empty():
self.__head=node
node.next = node
return
node.next=self.__head
cur=self.__head
while cur.next != self.__head:
cur=cur.next
cur.next=node
self.__head=node
def append(self, item):
node=Node(item)
if self.empty():
self.__head=node
node.next = node
return
cur=self.__head
while cur.next != self.__head:
cur=cur.next
cur.next = node
node.next = self.__head
def insert(self, pos, item):
node=Node(item)
if pos <= 0:
self.add(item)
elif pos > self.length()-1:
self.append(item)
else:
cur=self.__head
while pos>1:
cur=cur.next
pos -= 1
node.next=cur.next
cur.next=node
def search(self, item):
cur=self.__head
if not cur:
return False
#pos=0
while cur.next != self.__head:
if cur.item ==item:
return True
cur=cur.next
if cur.item ==item:
return True
return False
def remove(self, item):
pre=''
cur=self.__head
# empty
if not cur:
return
# only 1 element
if self.length() == 1:
if cur.item ==item:
self.__head = None
return
# more than 2 elements, 1st match
if cur.item ==item:
tmp=self.__head
while tmp.next != self.__head:
tmp=tmp.next
self.__head=cur.next
tmp.next=self.__head
return
# search 2th and after
while cur.next != self.__head:
if cur.item ==item:
pre.next=cur.next
return
pre=cur
cur=cur.next
#last one check
if cur.item ==item:
pre.next = self.__head
最后补充下 双向链表的实现:
定义 节点类 如下:
class Node():
def __init__(self, item):
# previous node address
self.pre = None
# data
self.item = item
# probe
self.next = None
以节点为基础,定义双向链表类及对应方法。
class double_table():
def __init__(self, node = None):
# head probe
self.__head = node
def empty(self):
return self.__head == None
def length(self):
if self.empty():
return 0
count=1
cur=self.__head
while cur.next != None:
count += 1
cur=cur.next
return count
def itersall(self):
if self.empty():
return
cur=self.__head
while cur.next != None:
print(cur.item,' ,', end='')
cur=cur.next
print(cur.item,' ,', end='')
print('')
def add(self, item):
node=Node(item)
if self.empty():
self.__head=node
return
self.__head.pre=node
node.next=self.__head
self.__head=node
def append(self, item):
node=Node(item)
if self.empty():
self.__head=node
return
cur=self.__head
while cur.next != None:
cur=cur.next
node.pre=cur
cur.next = node
def insert(self, pos, item):
node=Node(item)
if pos <= 0:
self.add(item)
elif pos > self.length()-1:
self.append(item)
else:
cur=self.__head
while pos>0:
cur=cur.next
pos -= 1
cur.pre.next=node
node.pre=cur.pre
node.next=cur
cur.pre=node
def search(self, item):
cur=self.__head
if not cur:
return False
#pos=0
while cur.next != None:
if cur.item ==item:
return True
cur=cur.next
if cur.item ==item:
return True
return False
def remove(self, item):
cur=self.__head
# empty
if not cur:
return
# only 1 element
if self.length() == 1:
if cur.item ==item:
self.__head = None
return
# more than 2 elements, 1st match
if cur.item ==item:
self.__head=cur.next
cur.next.pre=None
return
# search 2th and after
while cur.next != None:
if cur.item ==item:
cur.next.pre=cur.pre
cur.pre.next=cur.next
return
cur=cur.next
#last one check
if cur.item ==item:
cur.pre.next = None