python实现基础的数据结构(一)

本文涉及到的代码均已放置在我的github中 -->链接


python实现基础的数据结构(一)
python实现基础的数据结构(二)
python实现基础的数据结构(三)


python语法较为简洁,正好最近在复习数据结构,索性就用python去实现吧?
本文实现的有线性表、栈、队列、串、二叉树、图、排序算法。参照教材为数据结构(C语言版)清华大学出版社,还有网上的一些大神的见解。由于包含代码在内,所以内容很多,分了几篇,话不多说,我们直接步入正题?


注:本文实验环境:Anaconda 集成 python 3.6.5 ( 故代码为 python3 )
由于本文代码过多,故每一步不做太详细的介绍,我尽量在代码中解释细节,望体谅


线性表

线性表是最基本、最简单、也是最常用的一种数据结构。它的表示形式有两种,一种为顺序表示,一种为链式表示,我们来看第一种:

线性表的顺序表示

线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素,我这里实现了很基础的操作,我们直接看代码?:

#线性表
#线性表的顺序表示
class Lnode(object):
    """节点"""
    
    def __init__(self,last):#线性表定义
        self.data = [None for i in range(100)]
        self.last = last  #线性表长度


# 1.初始化建立空的线性表
def MakeEmpty(num):
  PtrL = Lnode(num)
  return PtrL

# 2.查找给定值的位置
def Find(x, L):
  i =0
  while(i <= L.last and L.data[i] != x):
    i+=1
  if(i> L.last):
    return False  #不符合要求输出False
  else:
    return i


# 3.插入(在第i(0<=i<=n)位置上插入一个值为x的新元素)
def Insert(x,i,L):
  if i<0 or i>L.last:
    print("位置不合理")
    return
  else:
    for j in range(L.last,i-1,-1):
      L.data[j+1] = L.data[j]
    L.data[i] = x
    L.last+=1
  return

# 4.删除第i(0<=i<=n-1)个位置上的元素
def Delete(i,L):
  if i<0 or i>=L.last:
    print("不存在该元素")
    return
  else:
    for j in range(i,L.last-1):
      L.data[j] = L.data[j+1]
    L.last -=1
    return


# 1、测试建立空的线性表
s = MakeEmpty(10)
print(s.data[0:s.last])
print(s.last)

# 2、测试查找函数
num = [0,1,2,3,4,5,6,7,8,9]
L = Lnode(10)
for i in range(10):
  L.data[i] = num[i]
print("建立新的线性表")
print(L.data[0:L.last])
print("查找元素2")
print("下标为:")
print(Find(2,L)) #此2非彼2,这里是第二个数的意思 不是数组下标
print("查找元素12")
print("下标为:")
print(Find(12,L)) 

# 3、测试插入函数
print("在位序3插入元素6")
Insert(6,3,L)
print(L.data[0:L.last])

# 4、测试删除函数
print("删除位序5的元素")
Delete(5,L)
print(L.data[0:L.last])

输出结果为:

[None, None, None, None, None, None, None, None, None, None]
10
建立新的线性表
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
查找元素2
下标为:
2
查找元素12
下标为:
False
在位序3插入元素6
[0, 1, 2, 6, 3, 4, 5, 6, 7, 8, 9]
删除位序5的元素
[0, 1, 2, 6, 3, 5, 6, 7, 8, 9]

线性表的链式表示

线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素。(这些存储单元可以是连续的,也可以是不连续的)。对于每一个数据元素来说(这里先忽略首尾)都包含两个域,一个是存储数据元素信息的域,叫数据域,另一个是存储直接后继存储位置的域,叫做指针域,我们来看代码:

#线性表
#线性表的链式表示
class Node(object):
    """节点"""
    def __init__(self, elem):
        self.elem = elem
        self.next = None  # 初始设置下一节点为空

# 下面创建单链表,并实现其应有的功能
class SingleLinkList(object):
    """单链表"""
    
    def __init__(self, node=None):  # 使用一个默认参数,在传入头结点时则接收,在没有传入时,就默认头结点为空
        self.__head = node
        
    def init_list(self, data):  # 按列表给出 data,初始化列表
        self.__head = Node(data[0])
        p = self.__head  # 指针指向头结点
        for i in data[1:]:
            p.next = Node(i)  # 确定指针指向下一个结点
            p = p.next  # 指针滑动向下一个位置
        
    def is_empty(self):
        '''判断链表是否为空'''
        return self.__head == None

    def length(self):
        '''链表长度'''
        cur = self.__head   # 遍历节点
        count =  0            #记录数量
        while cur != None:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        '''遍历整个列表'''
        cur = self.__head
        while cur != None:
            print(cur.elem, end=' ')
            cur = cur.next
        print("\n")

    def addhead(self, item):
        '''链表头部添加元素'''
        node = Node(item)
        node.next = self.__head
        self.__head = node

    def append(self, item):
        '''链表尾部添加元素'''
        node = Node(item)
        # 由于特殊情况当链表为空时没有next,所以在前面要做个判断
        if self.is_empty():
            self.__head = node
        else:
            cur = self.__head
            while cur.next != None:
                cur = cur.next
            cur.next = node

    def insert(self, pos, item):
        '''指定位置添加元素'''
        if pos <= 0:
                # 如果pos位置在0或者以前,那么都当做头插法来做
            self.addhead(item)
        elif pos > self.length() - 1:
            # 如果pos位置比原链表长,那么都当做尾插法来做
            self.append(item)
        else:
            per = self.__head
            count = 0
            while count < pos - 1:
                count += 1
                per = per.next
            # 当循环退出后,pre指向pos-1位置
            node = Node(item)
            node.next = per.next
            per.next = node

    def remove(self, item):
        '''删除节点'''
        cur = self.__head
        pre = None
        while cur != None:
            if cur.elem == item:
                # 先判断该节点是否是头结点
                if cur == self.__head:
                    self.__head = cur.next
                else:
                    pre.next = cur.next
                break
            else:
                pre = cur
                cur = cur.next
                
    def search(self, item):
        '''查找节点是否存在'''
        cur = self.__head
        while cur:
            if cur.elem == item:
                return True
            else:
                cur = cur.next
        return False
        
if __name__ == "__main__":
    #测试案例
    ll = SingleLinkList()
    print(ll.is_empty())
    print(ll.length())
   
    ll.init_list([1,5,6,65])#传入数组
    ll.travel()         #遍历输出
    ll.append(2)        #插入尾部
    ll.travel()
    ll.addhead(999)     #插入头部
    ll.travel()
    ll.insert(-3, 110)  #如果位置比0小插入头部,比len大插入尾部
    ll.travel()
    ll.insert(99, 111)
    ll.travel()
    print(ll.is_empty())
    print(ll.length())
    ll.remove(111)
    ll.travel()
    print(ll.search(22))
    print(ll.search(65))

输出结果为:

True
0
1 5 6 65 

1 5 6 65 2 

999 1 5 6 65 2 

110 999 1 5 6 65 2 

110 999 1 5 6 65 2 111 

False
8
110 999 1 5 6 65 2 

False
True

栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。栈是一种后进先出的数据结构(LIFO结构),表尾称为栈顶,表头称为栈底。最典型的例子就是你桌上的一摞书。栈有一个重要应用是在程序设计中实现递归操作,这里不详细讲述。由于python的列表操作过于强大,所以实现这个栈不是什么难事,代码如下?:

#栈

class Stack(object):
    """栈"""
    
    # 初始化栈为空列表
    def __init__(self):
        self.items = []
        
    def clearstack(self):
        self.items.clear()
        
    # 判断栈是否为空,返回布尔值
    def is_empty(self):
        return self.items == []

    # 返回栈顶元素 
    def gettop(self):
        if self.is_empty():  #一定要进行此步骤,否则会出现数组越界报错,下Pop同
            return '栈为空,无法进行你的操作'
        else:
            return self.items[-1]

    # 返回栈的大小
    def size(self):
        return len(self.items)

    # 把新的元素堆进栈里面
    def push(self, item):
        self.items.append(item)

    # 把栈顶元素丢出去,并且返回丢掉的数值
    def Pop(self):  			#大写Pop防止与python中list的pop操作混淆,这里换个函数名也可以
        if self.is_empty():
            return '栈为空,无法进行你的操作'
        else:
            return self.items.pop()


if __name__ == "__main__":
    
    # 初始化一个栈对象
    my_stack = Stack()
    my_stack.push('p')
    my_stack.push('y')
    
    print (my_stack.size())
    print (my_stack.gettop())
    print (my_stack.Pop())
    my_stack.clearstack()  
    print (my_stack.gettop())
    print (my_stack.is_empty())
    my_stack.push('p')
    my_stack.push('y')
    my_stack.push('t')
    my_stack.push('h')
    my_stack.push('o')
    my_stack.push('n')
    print (my_stack.size())
    print (my_stack.Pop())
    print (my_stack.size())
    print (my_stack.is_empty())

输出结果为:

2
y
y
栈为空,无法进行你的操作
True
6
n
5
False

队列

队列正好和栈是相反的,它是一种先进先出的线性表(FIFO),它只允许在表的一端进行插入,在另一端删除元素,也是一种受限制的线性表,所以进行队列操作时不能删除和插入中间元素,和我们日常排队是一致的(不考虑有人插队?),最早进入的元素最先离开,允许插入的一段叫做队尾,删除的一端叫做队头,代码如下(这里实现的是链式队列):

#链式队列

class Node(object):
    def __init__(self,value):
        self.data = value
        self.next = None
 
class Queue(object):
    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.is_empty():
            print('队空')
            return
        temp = self.front.next
        self.front.next = self.front.next.next
        if self.rear == temp:
            self.rear = self.front
        del temp
 
    def getHead(self):
        if self.is_empty():
            return '队空,无值输出'
        return self.front.next.data
 
    def is_empty(self):
        return self.rear == self.front

    #输出列
   def printQueue(self):
        cur = self.front.next
        tmp = ''
        while cur != None:
            tmp += cur.data
            cur = cur.next
        print(tmp)

    #清空列
    def clear(self):
        while self.front.next != None:
            temp = self.front.next
            self.front.next = temp.next
        self.rear = self.front

    #列长
    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('p')
    queue.enQueue('y')
    queue.enQueue('t')
    queue.enQueue('h')
    queue.enQueue('o')
    queue.enQueue('n')
    
    queue.printQueue()
    print()
    print(queue.is_empty())
    print(queue.length())
    print(queue.getHead())
    
    queue.deQueue()  
    print()
    queue.printQueue()
    print()
    print(queue.getHead())
    print()
    
    queue.clear()
    print(queue.length())
    print(queue.is_empty())
    print(queue.getHead())

输出结果为:

p
y
t
h
o
n

False
6
p

y
t
h
o
n

y

0
True
队空,无值输出

下一篇内容:串、二叉树和图
python实现基础的数据结构(二)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值