数据结构(合集)

目录

一、 AdjGraph

二、BinSearch

三、BTree

四、BreeSons

五、BTreeWidge

六、CSqQueue

八、LinkStack

九、Reverse

十、SeqSearch

十一、Sort

十二、SqList

十三、Tup


一、 AdjGraph

'''在教材源码AdjGraph.py,BFS1.py,DFS1.py的基础上,改编成单链表的形式实现邻接表。
1、先分别定义顶点结点,和边结点。
2、顶点结点存放于Python的list中,每个顶点结点作为单链表的头结点,指向自身所连的边结点,形成一条单链表。
3、同时改编图创建、图显示、广度优先遍历、深度优先遍历的方法。'''

from collections import deque

MAXV = 100  #表示最多顶点个数
INF = 0x3f3f3f3f  #表示∞


class ArcNode:  #边结点

    def __init__(self, adjv, w, adjvr):  #构造方法
        self.next = adjv  #下一个邻接点
        self.weight = w  #边的权值
        self.adjvex = adjvr  #邻接点


class verNode:  #顶点结点

    def __init__(self, adjv):  #构造方法
        self.next = adjv  #下一个邻接点


class AdjGraph:  #图邻接表类

    def __init__(self, n=0, e=0):  #构造方法
        self.adjlist = []  #邻接表数组
        self.vexs = []  #存放顶点信息,暂时未用
        self.n = n  #顶点数
        self.e = e  #边数

    def CreateAdjGraph(self, a, n, e):  # 通过数组a、n和e建立图的邻接表
        self.n = n  #置顶点数和边数
        self.e = e
        for i in range(n):  #检查边数组a中每个元素
            adi = verNode(None)  #存放顶点i的邻接点
            jun = adi
            for j in range(n):
                if a[i][j] != 0 and a[i][j] != INF:  #存在一条边
                    p = ArcNode(None, a[i][j], j)  #创建<j,a[i][j]>出边的结点p
                    jun.next = p  #将结点p添加到adi中
                    jun = p
            self.adjlist.append(adi)

    def DispAdjGraph(self):  #输出图的邻接表
        for i in range(self.n):  #遍历每一个顶点i
            print("  [%d]" % (i), end='')
            jun = self.adjlist[i].next
            while jun != None:
                print("->(%d,%d)" % (jun.adjvex, jun.weight), end='')
                jun = jun.next
            print("->∧")


def BFS(G, v):  #邻接表G中从顶点v出发的广度优先遍历
    MAXV = 100  #全局变量,表示最多顶点个数
    visited = [0] * MAXV
    qu = deque()  #将双端队列作为普通队列qu
    print(v, end=" ")  #访问顶点v
    visited[v] = 1  #置已访问标记
    qu.append(v)  #v进队
    while len(qu) > 0:  #队不空循环
        v = qu.popleft()  #出队顶点v
        m = G.adjlist[v]
        while m.next != None:
            w = m.next.adjvex
            m = m.next
            if visited[w] == 0:  #若w未访问
                print(w, end=" ")  #访问顶点w
                visited[w] = 1  #置已访问标记
                qu.append(w)  #w进队


def DFS(G, v):  #邻接表G中从顶点v出发的深度优先遍历
    MAXV = 100  #全局变量,表示最多顶点个数
    visited = [0] * MAXV
    print(v, end=' ')  #访问顶点v
    visited[v] = 1  #置已访问标记
    m = G.adjlist[v]
    while m.next != None:  #处理顶点v的所有出边顶点j
        w = m.next.adjvex
        if visited[w] == 0:
            DFS(G, w)  #若w顶点未访问,递归访问它
        m = m.next


if __name__ == '__main__':
    G = AdjGraph()
    n, e = 5, 5
    a = [[0, 8, INF, 5, INF], [INF, 0, 3, INF, INF], [INF, INF, 0, INF, 6],
         [INF, INF, 9, 0, INF], [INF, INF, INF, INF, 0]]
    G.CreateAdjGraph(a, n, e)
    G.DispAdjGraph()
    '''
    G = AdjGraph()
    n, e = 6, 7
    a = [[0, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1], [0, 0, 0, 1, 1, 1],
         [0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0]]
    G.CreateAdjGraph(a, n, e)
    print("图G")
    G.DispAdjGraph()
    print("BFS:", end=' ')
    BFS(G, 0)
    '''
    '''
    G = AdjGraph()
    n, e = 6, 7
    a = [[0, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1], [0, 0, 0, 1, 1, 1],
         [0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0]]
    G.CreateAdjGraph(a, n, e)
    print("图G")
    G.DispAdjGraph()
    print("DFS  ", end=' ')
    DFS(G, 0)'''

二、BinSearch

def BinSearch(R, k):  # 拆半查找非递归算法
    n = len(R)
    for x in range(len(k)):
        i = 0
        f = True
        ls = []
        low, high = 0, n - 1
        while low <= high:  # 当前区间非空时
            i += 1
            mid = (low + high) // 2  # 求查找区间的中间位置
            ls.append(R[mid])
            if k[x] == R[mid]:  # 查找成功返回其序号mid
                print('查找{},查找次数为{}次,查找过程中比较的数据为:{}'.format(
                    k[x], i,
                    str(ls)[1:-1]))  # 找到后返回其序号i
                f = False
            if k[x] < R[mid]:  # 继续在R[low..mid-1]中查找
                high = mid - 1
            else:  # k>R[mid]
                low = mid + 1  # 继续在R[mid+1..high]中查找
        if f:
            print('未找到{},查找次数为{}次,查找过程中比较的数据为:{}'.format(
                k[x], i,
                str(ls)[1:-1]))  # 找不到的情况


if __name__ == '__main__':
    R = [
        1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 17, 18, 19, 20, 24, 25, 26, 30,
        35, 40, 45, 50, 100
    ]
    K = [2, 8, 20, 30, 50, 5, 15, 33, 110]
    BinSearch(R, K)
    print()
    R = [
        2, 3, 5, 7, 8, 10, 12, 15, 18, 20, 22, 25, 30, 35, 40, 45, 50, 55, 60,
        80, 100
    ]
    K = [22, 8, 80, 3, 100, 1, 13, 120]
    BinSearch(R, K)

三、BTree

from collections import deque


class BTNode:  # 二叉链中结点类

    def __init__(self, d=None):  # 构造方法
        self.data = d  # 结点值
        self.lchild = None  # 左孩子指针
        self.rchild = None  # 右孩子指针


class BTree:  # 二叉树类

    def __init__(self, d=None):  # 构造方法
        self.b = None  # 根结点指针

    def SetRoot(self, r):  # 设置根结点为r
        self.b = r

    def DispBTree(self):  # 返回二叉链的括号表示串
        return self._DispBTree1(self.b)

    def _DispBTree1(self, t):  # 被DispBTree方法调用
        if t == None:  # 空树返回空串
            return ""
        else:
            bstr = t.data  # 输出根结点值
            if t.lchild != None or t.rchild != None:
                bstr += "("  # 有孩子结点时输出"("
                bstr += self._DispBTree1(t.lchild)  # 递归输出左子树
                if t.rchild != None:
                    bstr += ","  # 有右孩子结点时输出","
                bstr += self._DispBTree1(t.rchild)  # 递归输出右子树
                bstr += ")"  # 输出")"
            return bstr

    def FindNode(self, x):  # 查找值为x的结点算法
        return self._FindNode1(b, x)

    def _FindNode1(self, t, x):  # 被FindNode方法调用
        if t == None:
            return None  # t为空时返回null
        elif t.data == x:
            return t  # t所指结点值为x时返回t
        else:
            p = self._FindNode1(t.lchild, x)  # 在左子树中查找
            if p != None:
                return p  # 在左子树中找到p结点,返回p
            else:
                return self._FindNode1(t.rchild, x)  # 返回在右子树中查找结果

    def Height(self):  # 求二叉树高度的算法
        return self._Height1(b)

    def _Height1(self, t):  # 被Height方法调用
        if t == None:
            return 0  # 空树的高度为0
        else:
            lh = self._Height1(t.lchild)  # 求左子树高度lchildh
            rh = self._Height1(t.rchild)  # 求右子树高度rchildh
            return max(lh, rh) + 1


def PreOrder(bt):  # 先序遍历的递归算法
    PreOrder1(bt.b)


def PreOrder1(t):  # 被PreOrder方法调用
    if t != None:
        print(t.data, end=' ')  # 访问根结点
        PreOrder1(t.lchild)  # 先序遍历左子树
        PreOrder1(t.rchild)  # 先序遍历右子树


def InOrder(bt):  # 中序遍历的递归算法
    InOrder1(bt.b)


def InOrder1(t):  # 被InOrder方法调用
    if t != None:
        InOrder1(t.lchild)  # 中序遍历左子树
        print(t.data, end=' ')  # 访问根结点
        InOrder1(t.rchild)  # 中序遍历右子树


def PostOrder(bt):  # 后序遍历的递归算法
    PostOrder1(bt.b)


def PostOrder1(t):  # 被PostOrder方法调用
    if t != None:
        PostOrder1(t.lchild)  # 后序遍历左子树
        PostOrder1(t.rchild)  # 后序遍历右子树
        print(t.data, end=' ')  # 访问根结点


def LevelOrder(bt):  # 层次遍历的算法
    qu = deque()  # 将双端队列作为普通队列qu
    qu.append(bt.b)  # 根结点进队
    while len(qu) > 0:  # 队不空循环
        p = qu.popleft()  # 出队一个结点
        print(p.data, end=' ')  # 访问p结点
        if p.lchild != None:  # 有左孩子时将其进队
            qu.append(p.lchild)
        if p.rchild != None:  # 有右孩子时将其进队
            qu.append(p.rchild)


if __name__ == '__main__':
    b = BTNode('A')  # 建立各个结点
    p1 = BTNode('B')
    p2 = BTNode('C')
    p3 = BTNode('D')
    p4 = BTNode('E')
    p5 = BTNode('F')
    p6 = BTNode('G')
    b.lchild = p1  # 建立结点之间的关系
    b.rchild = p2
    p1.lchild = p3
    p3.rchild = p6
    p2.lchild = p4
    p2.rchild = p5
    bt = BTree()
    bt.SetRoot(b)
    print("bt:", end=' ')
    print(bt.DispBTree())
    x = 'X'
    p = bt.FindNode(x)
    if p != None:
        print("bt中存在" + x)
    else:
        print("bt中不存在" + x)
    print("bt的高度=%d" % (bt.Height()))
    print("先序序列:", end=' ')
    PreOrder(bt)
    print()
    print("中序序列:", end=' ')
    InOrder(bt)
    print()
    print("后序序列:", end=' ')
    PostOrder(bt)
    print()
    print("层次序列:", end=' ')
    LevelOrder(bt)
    print()

四、BreeSons

'''假设二叉树中每个结点值为单个字符,采用二叉链存储结构存储,设计一个算法,计算一棵给定二叉树bt中的所有单分支结点个数。'''


class BTNode:  # 二叉链中结点类

    def __init__(self, d=None):  # 构造方法
        self.data = d  # 结点值
        self.lchild = None  # 左孩子指针
        self.rchild = None  # 右孩子指针


class BTree:  # 二叉树类

    def __init__(self, d=None):  # 构造方法
        self.b = None  # 根结点指针

    def SetRoot(self, r):  # 设置根结点为r
        self.b = r

    def Sons(self):
        return self._Sons(self.b)

    def _Sons(self, t):
        if not t:
            return 0
        elif (not t.lchild and t.rchild) or (t.lchild and not t.rchild):
            return self._Sons(t.lchild) + self._Sons(t.rchild) + 1
        else:
            return self._Sons(t.lchild) + self._Sons(t.rchild)


if __name__ == '__main__':
    b = BTNode('A')  # 建立各个结点
    p1 = BTNode('B')
    p2 = BTNode('C')
    p3 = BTNode('D')
    p4 = BTNode('E')
    p5 = BTNode('F')
    p6 = BTNode('G')
    b.lchild = p1  # 建立结点之间的关系
    b.rchild = p2
    p1.lchild = p3
    p3.rchild = p6
    p2.lchild = p4
    p2.rchild = p5
    bt = BTree()
    bt.SetRoot(b)
    print("bt的单分支节点个数=%d" % (bt.Sons()))

五、BTreeWidge

'''假设二叉树采用二叉链存储结构,且所有结点值均不相同。设计一个算法,求二叉树的宽度(即二叉树中结点个数最多的那一层的结点个数)。'''

from collections import deque


class BTNode:  # 二叉链中结点类

    def __init__(self, d=None):  # 构造方法
        self.data = d  # 结点值
        self.lchild = None  # 左孩子指针
        self.rchild = None  # 右孩子指针


class BTree:  # 二叉树类

    def __init__(self, d=None):  # 构造方法
        self.b = None  # 根结点指针

    def SetRoot(self, r):  # 设置根结点为r
        self.b = r

    def Height(self):  # 求二叉树高度的算法
        return self._Height1(b)

    def _Height1(self, t):  # 被Height方法调用
        if not t:
            return 0  # 空树的高度为0
        else:
            lh = self._Height1(t.lchild)  # 求左子树高度lchildh
            rh = self._Height1(t.rchild)  # 求右子树高度rchildh
            return max(lh, rh) + 1

    def Width(self):
        sw = 0
        for i in range(1, self.Height() + 1):
            p = KCount1(self, i)
            if p > sw:
                sw = p
        return sw


class QNode:  # 队列元素类

    def __init__(self, l, p):  # 构造方法
        self.lev = l  # 结点的层次
        self.node = p  # 结点引用


def KCount1(bt, k):  # 求二叉树第k层结点个数
    cnt = 0  # 累计第k层结点个数
    qu = deque()  # 定义一个队列qu
    qu.append(QNode(1, bt.b))  # 根结点(层次为1)进队
    while len(qu) > 0:  # 队不空循环
        p = qu.popleft()  # 出队一个结点
        if p.lev > k:  # 当前结点的层次大于k,返回
            return cnt
        if p.lev == k:
            cnt += 1  # 当前结点是第k层的结点,cnt增1
        else:  # 当前结点的层次小于k
            if p.node.lchild:  # 有左孩子时将其进队
                qu.append(QNode(p.lev + 1, p.node.lchild))
            if p.node.rchild:  # 有右孩子时将其进队
                qu.append(QNode(p.lev + 1, p.node.rchild))
    return cnt


if __name__ == '__main__':
    b = BTNode('A')  # 建立各个结点
    p1 = BTNode('B')
    p2 = BTNode('C')
    p3 = BTNode('D')
    p4 = BTNode('E')
    p5 = BTNode('F')
    p6 = BTNode('G')
    b.lchild = p1  # 建立结点之间的关系
    b.rchild = p2
    p1.lchild = p3
    p3.rchild = p6
    p2.lchild = p4
    p2.rchild = p5
    bt = BTree()
    bt.SetRoot(b)
    print("bt的高度=%d" % (bt.Height()))
    print("bt的宽度=%d" % (bt.Width()))

六、CSqQueue

'''对于CSqQueue.py,增加以下3项基本运算
    1)增加一个数据成员变量priority,入队时指定元素的priority,
        使得出队列时priority最大的元素最先出列
    2)求队列中所有元素之和
    3)display队列中所有元素的值
'''

MaxSize = 100  #全局变量,假设容量为100


class CSqQueue:  #循环队列类

    def __init__(self):  #构造方法
        self.priority = [None] * MaxSize  #存放队列中元素优先级
        self.data = [None] * MaxSize  #存放队列中元素
        self.front = 0  #队头指针
        self.rear = 0  #队尾指针

    def empty(self):  #判断队列是否为空
        return self.front == self.rear

    def push(self, p, e):  #元素e进队
        assert (self.rear + 1) % MaxSize != self.front  #检测队满
        self.rear = (self.rear + 1) % MaxSize
        self.data[self.rear] = e
        self.priority[self.rear] = p

    '''
    def pop(self):  #出队元素
        assert not self.empty()  #检测队空
        self.front = (self.front + 1) % MaxSize
        return self.data[self.front]
    '''

    def pop(self):
        assert not self.empty()  #检测队空
        datap = dict()
        if self.rear < self.front:
            self.rear += MaxSize
        for i in range(self.rear - self.front):
            datap[self.priority[self.front + 1 + i]] = self.data[self.front +
                                                                 1 + i]
        data_p = sorted(datap.items(), key=lambda x: x[0], reverse=True)
        for i in range(1, self.rear - self.front + 1):
            self.data[self.front + i] = data_p[i - 1][1]
            self.priority[self.front + i] = data_p[i - 1][0]
        self.front = (self.front + 1) % MaxSize
        return self.data[self.front]

    def gethead(self):  #取队头元素
        assert not self.empty()  #检测队空
        head = (self.front + 1) % MaxSize  #求队头元素的位置
        return self.data[head]

    # 例3.11增加的方法
    def size(self):  #返回队中元素个数
        return ((self.rear - self.front + MaxSize) % MaxSize)

    def sumall(self):  # 求队列中所有元素之和
        assert self.front != self.rear  #检测空栈的异常
        s = 0
        self.p = self.front + 1
        for i in range(self.size()):
            s = s + self.data[self.p]  # type:ignore
            self.p = (self.p + 1) % MaxSize
        return s

    def display(self):  # display队列中所有元素的值
        self.p = self.front + 1
        for i in range(self.size()):
            print(self.data[self.p], end=' ')  # type:ignore
            self.p = (self.p + 1) % MaxSize
        print()


if __name__ == '__main__':
    qu = CSqQueue()
    qu.push(2, 6)
    qu.push(3, 7)
    qu.push(1, 5)
    qu.display()
    print(qu.empty())
    print(qu.gethead())
    print("队列中元素总和为{}".format(qu.sumall()))
    print("元素个数=%d" % (qu.size()))
    while not qu.empty():
        print(qu.pop(), end=' ')
    print()
    print("元素个数=%d" % (qu.size()))
'''
题目二:设计整数单链表的基本运算程序,并用相关数据进行测试
'''


# 单链表结点类
class LinkNode:

    # 构造函数
    def __init__(self, data=None) -> None:
        self.data = data  # data属性
        self.next = None  # next属性


# 线性表的单链表
class LinkList:

    # 构造函数
    def __init__(self) -> None:
        self.head = LinkNode()  # 头结点head
        self.head.next = None

    # 头插法——由数组a整体建立链表
    def CreateListF(self, a):
        for i in range(len(a)):
            s = LinkNode(a[i])  # 新建存放a[i]元素的结点s
            s.next = self.head.next  # 将s结点插入到开始结点之前,头结点之后
            self.head.next = s

    # 尾插法——由数组a整体建立链表
    def CreateListR(self, a):
        t = self.head
        for i in range(len(a)):
            s = LinkNode(a[i])  # 新建存放a[i]元素的结点s
            t.next = s  # 将s结点插入t结点之后
            t = s

    # 返回序号为i的结点
    def geti(self, i):
        p = self.head
        j = -1
        while (j < i and p is not None):
            j += 1
            p = p.next
        return p

    # 在线性表的末尾添加一个元素e
    def Add(self, e):
        s = LinkNode(e)  #新建存放e元素的结点s
        p = self.head
        while p.next:
            p = p.next
        p.next = s

    # 返回链表长度
    def getsize(self):
        p = self.head
        count = 0
        while p.next:
            count += 1
            p = p.next
        return count

    # 求序号为i的元素
    def __getitem__(self, i):
        return self.geti(i).data

    # 设置序号为i的元素
    def __setitem__(self, i, e):
        self.geti(i).data = e

    # 查找第一个为e的元素的序号
    def GetNo(self, e):
        j = 0
        p = self.head.next
        while p.data != e and p:
            j += 1
            p = p.next
        if p:
            return j
        return -1  # 未找到时返回-1

    # 在线性表中序号i位置插入元素e
    def Insert(self, i, e):
        s = LinkNode(e)  #新建存放e元素的结点s
        p = self.geti(i - 1)
        s.next = p.next
        p.next = s

    # 在线性表中删除序号i位置的元素
    def Delete(self, i):
        p = self.geti(i - 1)
        p.next = p.next.next  # 删除p结点的后继结点

    # 输出线性表
    def display(self):
        p = self.head.next
        while p:
            print(p.data, end=' ')
            p = p.next
        print()


# 测试数据
if __name__ == '__main__':
    L = LinkList()
    for i in range(1, 6):
        L.Add(i)
    print("L: ", end='')
    L.display()
    print("序号为2的元素=%d" % (L[2]))
    print("设置序号为2的元素为8")
    L[2] = 8
    print("序号为2的元素=%d" % (L[2]))
    n = L.getsize()
    print("size=%d" % (n))
    for i in range(0, n):
        print("删除%d序号的元素" % (0))
        L.Delete(0)
        print("L: ", end='')
        L.display()
    print("size=%d" % (L.getsize()))

    L1 = LinkList()
    a = [1, 2, 3, 4, 1]
    L1.CreateListR(a)
    print("L: ", end='')
    L1.display()
    print("序号为2的元素=%d" % (L1[2]))
    print("设置序号为2的元素为58")
    L1[2] = 58
    print("序号为2的元素=%d" % (L1[2]))
    i = 4
    x = 10
    print("在序号%d处插入%d" % (i, x))
    L1.Insert(i, x)
    print("L: ", end='')
    L1.display()

    i = 4
    print("删除序号%d处元素" % (i))
    L1.Delete(i)
    print("L: ", end='')
    L1.display()

    x = 20
    print("添加%d元素" % (x))
    L1.Add(x)
    print("L: ", end='')
    L1.display()
    print("元素1的序号是%d" % (L1.GetNo(1)))

八、LinkStack

'''題目一:
        将LinkStack.py改编成双向链表的栈,并增加以下两项运算:
        1)求栈中所有元素之和
        2)display栈中所有元素的值
'''


class LinkNode:  #双链表结点类

    def __init__(self, data=None):  #构造方法
        self.data = data  #data域
        self.next = None  #next域
        self.prior = None  #prior域


class LinkStack:  #链栈类

    def __init__(self):  #构造方法
        self.head = LinkNode()  #头结点head
        self.head.next = None
        self.head.prior = None

    def empty(self):  #判断栈是否为空
        if self.head.next == None:
            return True
        return False

    def push(self, e):  #元素e进栈  头插法
        p = LinkNode(e)
        p.next = self.head.next
        if self.head.next != None:  #修改头结点的非空后继结点的prior
            self.head.next.prior = p
        self.head.next = p  # type:ignore
        p.prior = self.head  # type:ignore 修改p结点的prior

    def pop(self):  #元素出栈
        assert self.head.next != None  #检测空栈的异常
        p = self.head.next
        p.prior.next = p.next  #修改p结点的前驱结点的next
        if p.next != None:  #修改p结点非空后继结点的prior
            p.next.prior = p.prior
        return p.data

    def gettop(self):  #取栈顶元素
        assert self.head.next != None  #检测空栈的异常
        return self.head.next.data

    def sumall(self):  #求栈中所有元素之和
        assert self.head.next != None  #检测空栈的异常
        p = self.head.next
        sumall = 0
        while p != None:
            sumall += p.data
            p = p.next
        return sumall

    def display(self):  # 打印栈中所有元素的值
        p = self.head.next
        while p:
            print(p.data, end=' ')
            p = p.next
        print()


if __name__ == '__main__':
    st = LinkStack()
    st.push(1)
    st.push(2)
    st.push(3)
    st.push(4)
    print(st.empty())
    print(st.gettop())
    print("栈中所有元素为", end=' ')
    st.display()
    print("栈中元素总和为:{}".format(st.sumall()))
    print("出栈顺序:", end=' ')
    while not st.empty():
        print(st.pop(), end=' ')
    print()

九、Reverse

# 2.用递归的方法编程实现输入的数字逆序输出:Reverse(n)
import sys

sys.setrecursionlimit(100000)  #递归的深度这里设置为十万
'''
def Reverse(n):
    if n != 0:
        print(n % 10)
    return Reverse(n // 10)

'''


def Reverse(n):
    print(n % 10, end='')
    if n // 10 != 0:
        Reverse(n // 10)


Reverse(120340)

十、SeqSearch

def SeqSearch1(R, k):  # 顺序查找算法1
    n = len(R)
    for x in range(len(k)):
        i = 0
        ls = []
        while i < n and R[i] != k[x]:
            ls.append(R[i])
            i += 1  # 从表头往后找
        if i > n:
            print('未找到{},查找次数为{}次,查找过程中比较的数据为:{}'.format(
                k[x], i,
                str(ls)[1:-1]))
        else:
            print('查找{},查找次数为{}次,查找过程中比较的数据为:{}'.format(
                k[x], i,
                str(ls)[1:-1]))  # 找到后返回其序号i


def SeqSearch2(R, k):  # 顺序查找算法2
    n = len(R)
    R.append(0)
    for x in range(len(k)):
        i = 0
        ls = []
        R[n] = k[x]  # 添加哨兵
        while R[i] != k[x]:
            ls.append(R[i])
            i += 1  # 从表头往后找
        if i == n:
            print('未找到{},查找次数为{}次,查找过程中比较的数据为:{}'.format(
                k[x], i,
                str(ls)[1:-1]))
        else:
            print('查找{},查找次数为{}次,查找过程中比较的数据为:{}'.format(
                k[x], i,
                str(ls)[1:-1]))  # 找到后返回其序号i


'''
R = [3, 9, 1, 5, 8, 10, 6, 7, 2, 4]
k = 6
print(SeqSearch1(R, k))
print(SeqSearch2(R, k))
'''
if __name__ == '__main__':
    R = [
        1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 17, 18, 19, 20, 24, 25, 26, 30,
        35, 40, 45, 50, 100
    ]
    K = [2, 8, 20, 30, 50, 5, 15, 33, 110]
    SeqSearch1(R, K)
    print()
    SeqSearch2(R, K)
    print()
    R = [
        2, 3, 5, 7, 8, 10, 12, 15, 18, 20, 22, 25, 30, 35, 40, 45, 50, 55, 60,
        80, 100
    ]
    K = [22, 8, 80, 3, 100, 1, 13, 120]
    SeqSearch1(R, K)
    print()
    SeqSearch2(R, K)

十一、Sort

'''
对教材中,直接插入排序源码InsertSort.py,
        冒泡排序源码BubbleSort.py,
        快速排序源码QuickSort.py,
        简单选择排序源码SelectSort.py,
        堆排序源码HeapSort.py进行简单改写,
使它们每一趟排序完成之后,输出该趟排序的结果。
注意要标出有序区域,如[1,6,9] 3, 8, 4,。深入理解不同算法的差别。
'''


def show(r):
    temp = ["["]
    f = 1
    for i in range(1, len(r)):
        if r[i] < r[i - 1] and f:
            temp.append(str(r[i - 1]))
            temp.append("]")
            temp.append(",")
            temp.append("[")
        elif r[i] > r[i - 1]:
            f = 1
            temp.append(str(r[i - 1]))
            temp.append(",")
        else:
            temp.append(str(r[i - 1]))
            temp.append(",")
    temp.append(str(r[-1]))
    temp.append("]")
    return temp


def InsertSort(R):
    for i in range(1, len(R)):
        if R[i] < R[i - 1]:
            tmp = R[i]
            j = i - 1
            while True:
                R[j + 1] = R[j]
                j -= 1
                if j < 0 or R[j] <= tmp:
                    break
            R[j + 1] = tmp
        print("".join(show(R)))
    return R


def BubbleSort(r):
    for i in range(len(r) - 1):
        exchange = 0
        for j in range(len(r) - 1, i, -1):
            if r[j] < r[j - 1]:
                r[j], r[j - 1] = r[j - 1], r[j]
                exchange = 1
        print("".join(show(r)))
        if not exchange:
            return r


def Partition3(r, s, t):
    i, j = s, s + 1
    base = r[s]
    while j <= t:
        if r[j] <= base:
            i += 1
            if i != j:
                r[j], r[i] = r[i], r[j]
        j += 1
    r[s], r[i] = r[i], r[s]
    return i


def QuickSort(r):
    QuickSort1(r, 0, len(r) - 1)
    return r


def QuickSort1(r, s, t):
    if s < t:
        i = Partition3(r, s, t)
        QuickSort1(r, s, i - 1)
        print("".join(show(r)))
        QuickSort1(r, i + 1, t)
        print("".join(show(r)))


def SelectSort(r):
    for i in range(len(r) - 1):
        minj = i
        for j in range(i + 1, len(r)):
            if r[j] < r[minj]:
                minj = j
        if minj != i:
            r[i], r[minj] = r[minj], r[i]
        print("".join(show(r)))
    return r


def SiftDown(low, high):
    global temp
    i = low
    j = 2 * i + 1
    tmp = temp[i]
    while j <= high:
        if j < high and temp[j] < temp[j + 1]:
            j += 1
        if tmp < temp[j]:
            temp[i] = temp[j]
            i, j = j, 2 * j + 1
        else:
            break
    temp[i] = tmp


def HeapSort():
    global temp
    n = len(temp)
    for i in range(n // 2 - 1, -1, -1):
        SiftDown(i, n - 1)
        print("".join(show(temp)))
    for i in range(n - 1, 0, -1):
        temp[0], temp[i] = temp[i], temp[0]
        SiftDown(0, i - 1)
        print("".join(show(temp)))


temp = [
    1, 2, 3, 4, 35, 40, 17, 26, 30, 45, 25, 10, 11, 6, 7, 8, 9, 18, 19, 20, 24,
    12, 13, 50, 100
]
# print("HeapSort")
# print(InsertSort(temp))
# print(BubbleSort(temp))
QuickSort(temp)
# print(SelectSort(temp))
# HeapSort()

十二、SqList

'''
题目一:设计整数顺序表的基本运算程序,并用相关数据进行测试
'''


# 线性表的顺序表
class SqList:

    # 构造函数
    def __init__(self) -> None:
        self.initcapacity = 50000000  # 初始容量设置为50000000,方便后面进行比较
        self.capacity = self.initcapacity  # 容量设置为初始容量
        self.data = [None] * self.capacity  # 设置顺序表的空间
        self.size = 0  # 长度设置为0

    # 改变顺序表的容量为newcapacity
    def resize(self, newcapacity):
        olddata = self.data
        self.data = [None] * newcapacity
        self.capacity = newcapacity
        for i in range(newcapacity):
            self.data[i] = olddata[i]

    # 由数组a中元素整体建立顺序表
    def CreateList(self, a):
        for i in range(len(a)):
            if self.capacity == self.size:  # 满时倍增容量
                self.resize(2 * self.capacity)
            self.data[self.size] = a[i]
            self.size += 1  # 添加后元素个数增加1

    # 在线性表的末尾添加一个元素e
    def Add(self, e):
        if self.capacity == self.size:  # 满时倍增容量
            self.resize(2 * self.capacity)
        self.data[self.size] = e  #添加元素e
        self.size += 1  # 添加后元素个数增加1

    # 返回长度
    def getsize(self):
        return self.size

    # 求序号为i的元素
    def __getitem__(self, i):
        return self.data[i]

    # 设置序号为i的元素
    def __setitem__(self, i, x):
        self.data[i] = x

    # 查找第一个为e的元素的序号
    def GetNo(self, e):
        i = 0
        while i < self.size and self.data[i] != e:
            i += 1
        if i >= self.size:
            return -1
        return i

    # 在线性表中序号i位置插入元素e
    def Insert(self, i, e):
        if self.capacity == self.size:  # 满时倍增容量
            self.resize(2 * self.capacity)
        for j in range(self.size, i, -1):  # 将data[i]及后面元素后移一个位置
            self.data[j] = self.data[j - 1]
        self.data[i] = e  # 插入元素e
        self.size += 1  # 长度增1

    def Delete(self, i):
        for j in range(i, self.size - 1):
            self.data[j] = self.data[j + 1]  # 将data[i]之后的元素前移一个位置
        self.size -= 1  # 长度减1
        if self.capacity > self.initcapacity and self.size <= self.capacity / 4:
            self.resize(self.capacity // 2)  # 满足要求容量减半

    # 输出顺序表
    def display(self):
        for i in range(self.size):
            print(self.data[i], end=' ')
        print()


# 测试数据
if __name__ == '__main__':
    L = SqList()
    for i in range(1, 6):
        L.Add(i)
    print("L: ", end='')
    L.display()
    f = L.GetNo(3)
    print("第一个为3的元素的序号为%d" % (L[f]))
    print("序号为2的元素=%d" % (L[2]))
    print("设置序号为2的元素为8")
    L[2] = 8
    print("序号为2的元素=%d" % (L[2]))
    n = L.getsize()
    print("size=%d" % (n))
    for i in range(0, n):
        print("删除%d序号的元素" % (0))
        L.Delete(0)
        print("L: ", end='')
        L.display()
    print("size=%d" % (L.getsize()))

十三、Tup

'''1.根据教材源码Tup.py,根据稀疏矩阵的三元组表示方法,将类TupClass补充完整,使其支持以下基本运算:
    (1) CreateTup(self,a, m.n):# 由m行n列的稀疏短阵A创建其三元组表示。
    (2) Setvalue(self,i,j, x):# 利用三元组给稀疏矩阵的元素赋值,即执行A[i,j]=x(为非零值)。
    (3) Getvalue(self,1j):# 利用三元组取稀疏矩阵的元素值即执行x=A[i,j]]。
    (4) DispTup(self):# 输出稀疏矩阵的三元组表示。'''


class TupElem:  # 三元组元素类

    def __init__(self, r1, c1, d1):  # 构造方法
        self.r = r1  # 行号
        self.c = c1  # 列号
        self.d = d1  # 元素值


class TupClass:  # 三元组表示类

    def __init__(self, rs, cs, ns):  # 构造方法
        self.rows = rs  # 行数
        self.cols = cs  # 列数
        self.nums = ns  # 非零元素个数(?)
        self.data = []  # 稀疏矩阵对应的三元组顺序表

    def CreateTup(self, A, m, n):  # 由m行n列(?)的稀疏矩阵A创建其三元组表示
        for i in range(m):
            for j in range(n):
                if A[i][j] != 0:
                    a = TupElem(i, j, A[i][j])
                    self.data.append(a)

    def Setvalue(self, i, j, x):  # 利用三元组给稀疏矩阵的元素赋值,即执行A[i][j]=x
        f = 0
        for c in range(len(self.data)):
            if self.data[c].r == i and self.data[c].c == j:
                self.data[c].d = x
                f = 1
                break
        if f == 0:
            for t in range(len(self.data)):
                if self.data[t].r >= i and self.data[t].c >= j:
                    if t != 0:
                        self.data.insert(t - 1, TupElem(i, j, x))
                    else:
                        self.data.insert(t, TupElem(i, j, x))
                    break

    def Getvalue(self, i, j):  # 利用三元组取稀疏矩阵的元素值,即执行x=A[i][j]
        for c in self.data:
            if c.r == i and c.c == j:
                return c.d
            else:
                return 0

    def DisTup(self):  # 输出稀疏矩阵的三元组表示
        for i in self.data:
            print(i.r, i.c, i.d)
        print()


if __name__ == "__main__":
    A = [[0, 0, 1], [4, 0, 0], [0, 5, 2]]
    L = TupClass(3, 3, 4)
    L.CreateTup(A, 3, 3)
    L.DisTup()
    L.Setvalue(0, 1, 6)
    L.DisTup()
    print(L.Getvalue(1, 2))
    print()
    L.DisTup()

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值