链表|栈|队列|树(Python实现)

链表


(单链表 双链表 循环链表)只是一个定义的结构而已 (数据结构不一样而已)
具体的对这个定义的操作要到这个定义实现的类当中去调用而已
在这里插入图片描述
概念区分

  • 头结点:是为了方便操作链表而附设的,头结点数据域通常用来保存跟链表有关的信息,比如链表的长度;

  • 首元结点:就是链表里“正式”的第一个结点,即链表的开始结点。形如a1,a2,a3,…an;

  • 头指针:头指针是指向链表的基地址。如果链表存在头结点则头指针就是指向头结点的地址,反之指向首元结点的地址。

#定义节点类型
class Node(object):
   def __init__(self,elem,next_=None):
       self.elem=elem
       self.next=next_

#定义单链表
class Linklist(object):
   def __init__(self,none=None):
       self.head=none
   #判断链表是否为空
   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('')
   #首部加元素
   def add(self,item):
       #将数据转换为节点类型
       node=Node(item)
       #新的节点指向首元节点
       node.next=self.head
       #新的节点变成首元节点
       self.head=node
   #尾部加元素
   def append(self,item):
       node=Node(item)
       #判断是否为空
       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:
           self.add(item)
       elif pos>(self.length()-1):
           self.append(item)
       else:
           node=Node(item)
           cur=self.head
           count=0
           while count<(pos-1):
               count+=1
               cur= cur.next
           node.next=cur.next
           cur.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
                   break
               else:
                   #从当前节点的前一个节点直接指向当前节点的下一个节点
                   pre.next=cur.next
                   break
           else:
               #当前节点不符合
               pre=cur#记录当前节点的位置
               cur=cur.next
       #查询某个值是否存在
   def search(self,item):
       cur=self.head
       while cur!=None:
           if cur.elem==item:
               return True
           else:
               cur=cur.next
       return False

if __name__=='__main__':
   linklist=Linklist()
   for i in range(5):
       linklist.append(i)
   linklist.travel()
   linklist.insert(3,7)
   linklist.travel()
   print(linklist.search(4))
   linklist.remove(7)
   linklist.travel()

特点:插入和删除操作只能在一个位置进行的表,该位置是表的末端,称为栈的顶(top)。
先进后出

具体操作

  • Stack() 创建一个新的空栈
  • push(item) 添加一个新的元素item到栈顶
  • pop() 弹出栈顶元素
  • peek() 返回栈顶元素
  • is_empty() 判断栈是否为空
  • size() 返回栈的元素个数
"""
Stack() 创建一个新的空栈
push(item) 添加一个新的元素item到栈顶
pop() 弹出栈顶元素
peek() 返回栈顶元素
is_empty() 判断栈是否为空
size() 返回栈的元素个数
"""
class Stack(object):
    def __init__(self):
        self.items=[]
    def is_empty(self):
        return self.items==[]
    #入栈
    def push(self,item):
        self.items.append(item)
    #弹出栈顶
     def pop(self):
        if self.is_empty():
            raise IndexError
        self.items.pop()
    #返回栈顶元素
    def peek(self):
        return self.items[self.size()-1]
    #获取栈长度
    def size(self):
        return len(self.items)


if __name__=='__main__':
    stack=Stack()
    for i in range(0,10):
        stack.push(i)
    print(stack.size())
    print(stack.is_empty())
    print(stack.peek())
    stack.pop()
    print(stack.peek())

队列

特点:插入和删除在不同的端进行。队列的基本操作是Enqueue(入队),在表的末端(rear)插入一个元素,还有出列(Dequeue),删除表开头的元素。
先进先出.

"""
Queue() 创建一个新的空栈
enqueue(item) 添加一个新的元素item到队列底部
delqueue() 弹出队首元素
is_empty() 判断队列是否为空
size() 返回队列的元素个数
"""
class Queue(object):
    def __init__(self):
        self.queues=[]
    def is_empty(self):
        return self.queues==[]
    def enqueue(self,queue):
        self.queues.append(queue)
    def delqueue(self):
        if self.is_empty():
            raise IndexError
        val=self.queues[0]
        self.queues.remove(val)
        return val
    def size(self):
        return len(self.queues)
if __name__=='__main__':
    queue=Queue()
    print(queue.is_empty())
    for i in range(10):
        queue.enqueue(i)
    print(queue.size())
    print(queue.delqueue())
    print(queue.delqueue())

(英语:tree)是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:

  • 每个节点有零个或多个子节点;
  • 没有父节点的节点称为根节点;
  • 每一个非根节点有且只有一个父节点;
  • 除了根节点外,每个子节点可以分为多个不相交的子树;

树的术语

  • 节点的度:一个节点含有的子树的个数称为该节点的度;
  • 树的度:一棵树中,最大的节点的度称为树的度;
  • 叶节点或终端节点:度为零的节点;
  • 父亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;
  • 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;
  • 兄弟节点:具有相同父节点的节点互称为兄弟节点;
  • 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
  • 树的高度或深度:树中节点的最大层次;
  • 堂兄弟节点:父节点在同一层的节点互为堂兄弟;
  • 节点的祖先:从根到该节点所经分支上的所有节点;
  • 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。
  • 森林:由m(m>=0)棵互不相交的树的集合称为森林;

树的种类

  • 无序树:树中任意节点的子节点之间没有顺序关系,这种树称为无序树,也称为自由树;
  • 有序树:树中任意节点的子节点之间有顺序关系,这种树称为有序树;
  • 二叉树:每个节点最多含有两个子树的树称为二叉树;
  • 完全二叉树:对于一颗二叉树,假设其深度为d(d>1)。除了第d层外,其它各层的节点数目均已达最大值,且第d层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树x
  • 满二叉树:所有分支节点的度都是2
  • 平衡二叉树(AVL树):当且仅当任何节点的两棵子树的高度差不大于1的二叉树;
  • 排序二叉树(二叉查找树(英语:Binary Search Tree),也称二叉搜索树、有序二叉树);
  • 霍夫曼树(用于信息编码):带权路径最短的二叉树称为哈夫曼树或最优二叉树;
  • B树:一种对读写操作进行优化的自平衡的二叉查找树,能够保持数据有序,拥有多余两个子树。

树的存储与表示

顺序存储:将数据结构存储在固定的数组中,然在遍历速度上有一定的优势,但因所占空间比较大,是非主流二叉树。二叉树通常以链式存储。

常见的一些树的应用场景

  1. xml,html等,那么编写这些东西的解析器的时候,不可避免用到树
  2. 路由协议就是使用了树的算法
  3. mysql数据库索引
  4. 文件系统的目录结构
  5. 所以很多经典的AI算法其实都是树搜索,此外机器学习中的decision tree也是树结构
#定义树的节点
class Node(object):
    def __init__(self,item):
        self.elem=item
        self.lchild=None
        self.rchild=None

#定义树
class Tree():
    def __init__(self):
        self.root=None
    #添加树
    def add(self,item):
        node=Node(item)
        if self.root==None:
            #如果根节点为空
            self.root=node
        else:
            queue=[]
            queue.append(self.root)
            while queue:
                cur_node=queue.pop(0)
                #取出列表第一个元素额
                if cur_node.lchild is None:
                    cur_node.lchild=node
                    return
                else:
                    #如果当前节点的左子树不为空将其添加至列表中
                    queue.append(cur_node.lchild)
                if cur_node.rchild is None:
                    cur_node.rchild =node
                    return
                else:
                    queue.append(cur_node.rchild)

    #广度遍历非递归
    def breadth_travel(self):
        if self.root==None:
            return
        queue=[]
        queue.append(self.root)
        while queue:
            node=queue.pop(0)
            print(node.elem,end=' ')
            if node.lchild!=None:
                queue.append(node.lchild)
            if node.rchild!=None:
                queue.append(node.rchild)
        print('')

    def breadth_travel_two(self):
        if self.root==None:
            return
        queue=[]
        queue.append(self.root)
        while queue:
            length=len(queue)
            for i in range(length):
                node=queue.pop(0)
                print(node.elem,end=' ')
                if node.lchild != None:
                    queue.append(node.lchild)
                if node.rchild != None:
                    queue.append(node.rchild)
        print('')

    #深度遍历 非递归 前序遍历 根 左 右
    def deep_travel_qianxu(self):
        if self.root==None:
            return
        queue=[]
        queue.append(self.root)
        while queue:
            cur=queue.pop()
            print(cur.elem,end=' ')
            #前序遍历 根 左 右
            #先放入右节点再放入作节点
            if cur.rchild is not None:
                queue.append(cur.rchild)
            if cur.lchild is not None:
                queue.append(cur.lchild)
        print('')
    #左根右
    """
    1. 使用一个栈保存结点(列表实现);
    2. 如果结点存在,入栈,然后将当前指针指向左子树,直到为空;
    3. 当前结点不存在,则出栈栈顶元素,并把当前指针指向栈顶元素的右子树;
    4. 栈不为空,循环2、3。
    """
    def deep_travel_zhongxu(self):

        if not self.root:
            return
        stack = []
        cur=self.root
        while cur or stack:
            #将当前节点的左节点都入栈
            while cur:
                stack.append(cur)
                cur = cur.lchild
            # 获取当前最左节点
            if stack:
                a = stack.pop()
                cur = a.rchild
                print(a.elem,end=' ')
        print('')
    #左 右 根
    def deep_travel_houxu(self):
        cur=self.root
        stack = [cur]
        stack2 = []
        while len(stack) > 0:
            cur = stack.pop()
            stack2.append(cur)
            if cur.lchild:
                stack.append(cur.lchild)
            if cur.rchild:
                stack.append(cur.rchild)
        while len(stack2) > 0:
            node = stack2.pop()
            print(node.elem,end=' ')

        print('')

    #深度遍历递归
    def preorder(self, node):
        # 先序遍历 根 左 右
        if node == None:
            return
        print(node.elem, end=" ")
        self.preorder(node.lchild)
        self.preorder(node.rchild)

    def inorder(self, node):
        # 中序遍历 左 根 右
        if node == None:
            return
        self.inorder(node.lchild)
        print(node.elem, end=" ")
        self.inorder(node.rchild)

    def proorder(self, node):
        # 后序遍历 左 右 根
        if node == None:
            return
        self.inorder(node.lchild)
        self.inorder(node.rchild)
        print(node.elem, end=" ")

if __name__=='__main__':
    tree=Tree()
    for i in range(7):
        tree.add(i)
    tree.breadth_travel_two()
    print("*"*20)
    tree.deep_travel_qianxu()
    print("*" * 20)
    tree.deep_travel_zhongxu()
    print("*"*20)
    tree.deep_travel_houxu()
/* * 基于链表实现结构 */ package dsa; public class TreeLinkedList implements Tree { private Object element;//根节点 private TreeLinkedList parent, firstChild, nextSibling;//父亲、长子及最大的弟弟 //(单节点)构造方法 public TreeLinkedList() { this(null, null, null, null); } //构造方法 public TreeLinkedList(Object e, TreeLinkedList p, TreeLinkedList c, TreeLinkedList s) { element = e; parent = p; firstChild = c; nextSibling = s; } /*---------- Tree接口中各方法的实现 ----------*/ //返回当前节点中存放的对象 public Object getElem() { return element; } //将对象obj存入当前节点,并返回此前的内容 public Object setElem(Object obj) { Object bak = element; element = obj; return bak; } //返回当前节点的父节点;对于根节点,返回null public TreeLinkedList getParent() { return parent; } //返回当前节点的长子;若没有孩子,则返回null public TreeLinkedList getFirstChild() { return firstChild; } //返回当前节点的最大弟弟;若没有弟弟,则返回null public TreeLinkedList getNextSibling() { return nextSibling; } //返回当前节点后代元素的数目,即以当前节点为根的子的规模 public int getSize() { int size = 1;//当前节点也是自己的后代 TreeLinkedList subtree = firstChild;//从长子开始 while (null != subtree) {//依次 size += subtree.getSize();//累加 subtree = subtree.getNextSibling();//所有孩子的后代数目 } return size;//即可得到当前节点的后代总数 } //返回当前节点的高度 public int getHeight() { int height = -1; TreeLinkedList subtree = firstChild;//从长子开始 while (null != subtree) {//依次 height = Math.max(height, subtree.getHeight());//在所有孩子中取最大高度 subtree = subtree.getNextSibling(); } return height+1;//即可得到当前节点的高度 } //返回当前节点的深度 public int getDepth() { int depth = 0; TreeLinkedList p = parent;//从父亲开始 while (null != p) {//依次 depth++; p = p.getParent();//访问各个真祖先 } return depth;//真祖先的数目,即为当前节点的深度 } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值