数据结构与算法 向量

85 篇文章 0 订阅

#coding=gbk
'''
栈、队列和链表、向量(python中的列表,C中的数组)一样,
都是线性的数据结构(对于数据结构中的任何一个元素,都具有唯一的前驱和唯一的后继)

栈:在任意一个时刻,只有栈顶元素是允许访问的,栈中的任何其他元素都是禁止访问的
开放的一端称为栈的顶端(top),不开放的那一端称为底部(bottom)
向栈中添加元素:只能向栈的顶部添加元素
从栈中取出元素:只能从栈的顶部取出元素,栈顶元素被取出后,栈中的其余元素将会
依次向前替补,则将会出现新的栈顶元素。

向量:所有的元素在逻辑上和在物理上彼此都是紧邻排列,所有的元素之间没有任何缝隙

'''

class Vector(object):
    def __init__(self):
        # 初始化栈对象
        self.item=[-float('inf'),float('inf')]
        # 初始状态下的列表仅仅包含两个虚拟的哨兵节点
        self.length=0
    def size(self):
        return self.length
    def empty(self):
        return self.length==0
    def get(self,r):
        # 获取秩为r的元素
        if r<0 or r>self.length:
            print('r must between :%d and :%d'%(0,self.length))
            return
        else:
            return self.item[r+1]
    def put(self,r,e):
        # 用e替换秩为r元素的数值
        self.item[r+1]=e
    def insert(self,r, e):
        # e作为秩为r元素插入,原后继依次后移
        self.item.append(float('inf'))
        # 将秩为r的元素以及之后的元素分别向后移动
        # 将秩为r的元素以及它所有后缀的子序列整体向后移动一个单元
        for i in range(self.length,r,-1):
            self.item[i+1]=self.item[i]
        self.item[r+1]=e
        self.length += 1
    def remove(self,r):
        # 删除秩为r的元素,返回该元素原值
        # 删除操作的主要复杂度来源于:将秩为r的所有元素的后继向前移动一个单位
        # 共需要进行self.length-r 次移动操作
        # 通过调用remove接口函数逐个删除单个元素的方法来删除整个向量
        # 所需要的时间复杂度是O(n**2)
        output=self.item[r+1]
        for i in range(r+1,self.length+1):
            self.item[i]=self.item[i+1]
        del self.item[-1]
        # print('jsdijs------------', output,self.item)
        self.length-=1
        return output
    def disordered(self):
        # 判断所有元素是否已按非降序排列
        # 返回当前栈中紧邻逆序对的个数,如果紧邻逆序对个数不为0,则说明当前的数组没有排序好
        # 向量是否有序:当且仅当向量中是否存在紧邻的逆序对
        count=0
        for i in range(1,self.length):
            # 对于数组中的每个元素,如果当前元素大于它紧邻的下一个元素,则它们是一对紧邻逆序对
            if self.item[i]>self.item[i+1]:
                count+=1
            # print('here',self.item[i],self.item[i+1],count)
        return count

    def find(self,e):
        # 查找目标元素e
        # 实际上是查找:在当前向量中是否有元素等于e的第一个元素,
        # 如果当前列表中不存在元素e,则返回-1
        for i in range(1,self.length+1):
            if self.item[i]==e:
                return i-1
        return -1
    def find_Pos_eq(self,start,len,e):
        '''
        从下标start开始的长度为len的子序列中,找到第一个等于e的元素的下标
        如果找不到则返回-1
        :param start:
        :param len:
        :param e:
        :return:
        '''
        for i in range(len):
            if self.item[start]==e:
                return start-1
        return -1
    def search(self,e):
        '''
        返回在当前向量中,不超过数值e的最大元素的秩序,这是对于有序向量所使用的查找方法
        :param e:
        :return:
        '''
        if self.disordered()==0:#假设当前的向量是有序向量
            index=-1
            for i in range(0,self.length+1):
                if self.item[i]<=e:
                    # print('here',self.item[i])
                    index=i-1
            return index

    def find_Pos(self,start_index,len,e):
        '''
        在当前的向量中,从索引下标start_index开始的len个元素(包括start_index)
        找到第一个大于元素e的秩,并返回,如果没有找到(即当前有序的前缀子序列中
        所有元素的数值都小于数值e,则返回-1)
        :param start_index:
        :param e:
        :return:
        '''
        for i in range(len):
            if self.item[start_index]>e:
                return start_index-1
            else:
                start_index+=1
        return -1

    def sort(self):
        # 调整各元素的位置,使之按非降序排列
        # 使用插入排序算法,在排序算法家族中,插入排序算法在最好情况下的时间复杂度是O(n)
        # 即在每次迭代中,刚好查找一次就能找到当前元素在有序前缀子序列中被插入的合适位置
        # 则每次迭代实际上只需要insert操作,即当前元素比有序子序列的第一个元素都小,时间复杂度为O(1)
        # 插入排序在最坏的情况下时间复杂度是O(n**2)
        # 即:在每次迭代中,当前秩为r元素必须遍历了前面的r个有序前缀子序列中的元素,才能找到它的插入位置
        # 则比较总数:1+2+……n-1=O(n**2) 插入的时间复杂度O(n)
        if self.length<=1:
            return
        start = 1
        len_sorted=1
        curr = start + 1
        # 初始化有序前缀子序列的长度为1
        for i in range(self.length-1):
            # print('here',i,self.traverse())
            pos=self.find_Pos(start,len_sorted,self.item[curr])
            # print(pos)
            if pos!=-1:
                self.insert(pos,self.item[curr])
                self.remove(curr)
            curr+=1
            len_sorted+=1

    def uniquify(self):
        assert self.disordered()==0
        # 对于有序向量,进行去重,时间复杂度O(n**2)
        if self.length<=1:
            return
        value=self.item[1]
        num=self.length+1
        i=2
        while(self.item[i]<self.item[-1]):
            # print(self.traverse())
            if self.item[i]==value:
                self.remove(i-1)
            else:
                value=self.item[i]
            i+=1
    def ununiquify_faster(self):
        '''
        对于有序向量去重的高效算法,时间复杂度O(n)
        :return:
        '''
    def deduplicate(self):
        '''
        实现对于无序向量的去重操作,与双向链表的去重操作完全相同
        将当前的向量分割成如下三个部分:
        没有重复元素的前缀子序列,当前所要考察的元素curr,没有考察的后缀子序列
        如果curr出现在前缀子序列中,则删除curr元素,curr指针向后移动一位
        否则,将前缀子序列的长度扩展一位
        :return:
        '''
        if self.length<=1:
            return # 平凡序列必然不包含重复元素

        start=1
        len_right=1
        curr=start+1
        # print(self.traverse())
        while(self.item[curr]<self.item[-1]):
            pos=self.find_Pos_eq(start,len_right,self.item[curr])
            # print('here', self.traverse(), pos)
            if pos!=-1:#说明curr元素存在于前缀子序列中
                self.remove(curr-1)
            else:
                curr+=1
                len_right+=1

    def traverse(self):
        return self.item[1:-1]

if __name__=='__main__':
    vector_1=Vector()
    vector_1.insert(0,9)
    print(vector_1.traverse())
    vector_1.insert(0, 4)
    print(vector_1.traverse())
    vector_1.insert(1, 5)
    print(vector_1.traverse())
    vector_1.put(1,2)
    print(vector_1.traverse())
    print(vector_1.get(2))
    vector_1.insert(3,6)
    print(vector_1.traverse())
    vector_1.insert(1,7)
    print(vector_1.traverse())
    vector_1.remove(2)
    print(vector_1.traverse())
    vector_1.insert(1,3)
    print(vector_1.traverse())
    vector_1.insert(3,4)
    print(vector_1.traverse())
    print(vector_1.size())
    print(vector_1.disordered())
    print(vector_1.find(9))
    print(vector_1.find(5))

    vector_1.deduplicate()
    print('sdhfijdsjfs',vector_1.traverse())

    exit()

    vector_1.sort()
    print(vector_1.traverse())
    print(vector_1.disordered())
    print(vector_1.search(1))
    print(vector_1.search(4))
    print(vector_1.search(8))
    print(vector_1.search(9))
    print(vector_1.search(10))
    vector_1.uniquify()
    print(vector_1.traverse())
    print(vector_1.search(9))



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值