python数据结构实现(一)

一:数组

1. 线性表的顺序存储结构一般特性:

  • 支持随机访问
  • 占用连续的存储空间,长度不可改变

python本身没有数组结构,虽然列表可以完成数组的基本功能,也可通过嵌套实现多维列表,但是当数据量较大时,速度会变慢。通常我们可以利用array模块或Numpy里封装的array()创建数组。

2. python实现支持动态扩容的数组

在这里,基于Python的列表实现动态数组的创建。

class DynamicArr:
    def __init__(self, capacity=20):
        '''
        构造函数
        :param capacity:数组容量大小,默认为20
        '''
        self._capacity = capacity
        self._length = 0      # 数组的有效长度
        # 基于列表实现,通过赋值None实现底层具有连续的内存空间,容量固定的数组
        self._data = [None] * self._capacity

    def __getitem__(self, index):
        '''使得DynamicArr类实例化对象支持索引随机访问'''
        return self._data[index]

    def __setitem__(self, index, value):
        '''使得DynamicArr类实例化对象支持直接赋值'''
        self._data[index] = value

    def getLength(self):
        '''返回当前数组长度'''
        return self._length

    def getCapacity(self):
        '''返回数组容量'''
        return self._capacity

    def add(self, index, value):
        '''
        往数组增加一个元素
        :param index:待添加元素在数组的目标下标
        :param value:待添加元素的值
        
        '''
        if index < 0 or index > self._length:  # 无效的插入位置
            raise Exception('invaild index: require 0 <= index <= self._size')
        if self._length == self._capacity:  # 数组已满
            # 将数组容量扩充至两倍,比单独扩充一个单位要好,均摊复杂度为O(1)
            self._resize(self._capacity*2)  
            
        for i in range(self._size, index-1, -1):
            self._data[i+1] = self._data[i]
        self._data[index] = value
        self._length += 1

    def addLast(self, value):    # 往数组的末尾添加元素
        return self.add(self._length, value)

    def _resize(self, newCapacity):
        '''
        重构数组的容量
        :param newCapacity:新的容量大小
        
        '''
        newArr = DynamicArr(newCapacity)
        for i in range(self._length):
            newArr.addLast(self._data[i])
        self._capacity = newArr._capacity
        self._data = newArr._data

3.python实现固定容量的有序数组

class StaticOrderArr:
    def __init__(self, capacity=20):    # 数组默认容量为20
        self._capacity = capacity
        self._length = 0
        self._data = [None] * self._capacity

    def __getitem__(self, index):
        return self._data[index]

    def __setitem__(self, index, value):
        '''使数组支持更改操作'''
        if index <= self._length and index >= 0:
            if index == 0 or index == self._length-1:
                self._data[index] = value
            else:
                if self._data[index-1] <= value and self._data[index+1] >= value:
                    self._data[index] = value
                else:
                    raise Exception('set failed: require value meets the demand of order')
        else:
            raise Exception('set failed: invaild index')

    def add(self, value):
        '''
        往有序数组添加值为value的元素
        '''
        if self._length == self._capacity:
            raise Exception('The arrary is full')
        elif self._length == 0:
            self._data[0] = value
            self._length += 1
        else:
            for i in range(self._length-1, -1, -1):
                if self._data[i] > value:
                    self._data[i+1] = self._data[i]
                else:
                    self._data[i+1] = value
                    self._length += 1
                    break
        if self._data[0] > value:
                self._data[0] = value
                self._length += 1
                
    def remove(self, index):
        '''删除有序数组中下标为index的元素'''
        if self._length == 0:
            raise Exception('remove failed: Array is empty')
        if index < 0 or index > self._length:
            raise Exception('invaild index,require 0 <= index <= self._length')
        else:
            for i in range(index+1,self._length,1):
                self._data[i-1] = self._data[i]
            self._length -= 1
            
    def getLength(self):
        return self._length

    def getCapacity(self):
        return self._capacity

4. python实现两个有序数组合并为一个有序数组

def isorder(arr=[]):
    '''
    判断数组是否有序
    '''
    arrSize = len(arr)
    flag = True
    
    if not arr:
        flag = True
    else:
        for i in range(arrSize-1):
            if arr[i] < arr[i+1]:
                pass
            else:
                flag = False
    return flag

def mergeSort(arr1=[],arr2=[]):
    newArr = []

    if isorder(arr1) and isorder(arr2):       # 判断参数的合理性
        if not arr1:                          # 当参数存在空数组的情况
            newArr = arr2
        elif not arr2:
            newArr = arr1
        else:                                 # 当参数为两个有序数组的情况
            i = j = 0
            len1 = len(arr1);len2 = len(arr2)
            
            while i < len1 and j < len2:    
            	'''循环比较两个数组之间相对位置的元素大小,将较小的元素放入到新的数组中,直到有一组排序完毕'''
                if arr1[i] <= arr2[j]:
                    newArr.append(arr1[i])
                    i += 1
                else:
                    newArr.append(arr2[j])
                    j += 1
                    
            while i < len1:                 # 当arr1没有排序完毕
                newArr.append(arr1[i])
                i += 1
            
            while j < len2:                 # 当arr2没有排序完毕
                newArr.append(arr2[j])
                j += 1
                
            return newArr
        
    else:
        print('待排序的数组要求必须有序!')

5. leetcode相关习题

(1). 两数之和(1)

用哈希表思想实现:

class Solution:
    def twoSum(self, nums, target):
        hash_dict = dict()
        for i in range(len(nums)):
            num = nums[i]
            if hash_dict.get(target - num) == None:
                hash_dict[num] = i
            else:
                return [hash_dict[target - num], i]
s = Solution()
s.twoSum([1,3,5,8,2,-1],10)

(2). Happy Number(202)

用哈希表思想实现:当某个值第二次出现时,则开始进入循环,此时可直接判断该数不是快乐数

class Solution:
    def isHappy(self, n):
        hash_set = dict()
        while True:
            if hash_set.get(n) == None:
                hash_set[n] = 1
                num = str(n)
                length = len(num)
                n = 0
                for i in range(length):
                    n += int(num[i]) ** 2
                if n == 1:
                    flag = True
                    break
                else:
                    num = n
            else:
                flag = False
                break
        return flag

(3). Three Sum(求三数之和)

采用的思路是:遍历数组arr,再对target - arr[i]采用两数之和的求解方法,则arr[i]与两数之和函数所返回的列表[n1, n2]则可组成一个所求解。

def twoSum(nums, target):
    hash_table = dict()
    length = len(nums)
    result = []
    for i in range(length):
        if hash_table.get(target - nums[i]) == None:
            hash_table[nums[i]] = True
        else:
            result.append([target - nums[i], nums[i]])
    return result

def threeSum(nums, target):
    length = len(nums)
    hash_table = dict()
    result = []
    for i in range(length):
        target2 = target - nums[i]
        if hash_table.get(nums[i]) == None:
            hash_table[nums[i]] = True
            temps = twoSum(nums[:i] + nums[i+1:], target2)
            if temps:
                for temp in temps:
                    temp.append(nums[i])
                    result.append(temp)
    
    result_final = [list(t) for t in set(tuple(_) for _ in result)]
        
    return result_final

(4). Majority Element(求众数)

思路:直接遍历,将第一个元素做初始比较数,设置一个count计数器,初始为1。遍历数组,当遇到相同值则+1,遇到不同值则-1,当count为零时,则将比较数改为当前数组元素。

class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        length = len(nums)
        count = 1
        comp = nums[0]
        for i in range(1,length):
            if nums[i] == comp:
                count += 1
            else:
                count -= 1
                if count == 0:
                    comp = nums[i]
                    count = 1
        return comp

(5). Missing Positive(求缺失的第一个正数)

采用思路:利用哈希思想,遍历数组,对其中大于等于零的元素进行hash。遍历完数组后,从1开始遍历哈希表,遇到的第一没有访问过的值即为所求缺失的第一个正数

def firstMissingPositive(nums):
    hash_table = dict()
    maxPostive = -1
    if not nums:       # 数组为空
            return 1
    for num in nums:
        if num >= 0 and hash_table.get(num) == None:
            hash_table[num] = True
            if maxPostive < num:
                maxPostive = num
                
    if maxPostive == -1:      # 数组中没有正数
        return 1
    
    for i in range(1, maxPostive+2):      # maxPostive+2 : 当所求最小正整数为数组中最大正数+1时
        if hash_table.get(i) != True:
            return i

二:链表

1. 用python实现单链表

class linkedList:
    def __init__(self, data, pnext=None):
        self.data = data
        self.next = pnext
        
# 打印链表
def show(node):
    p = node
    while p:
        print(p.data, end = ' ')
        p = p.next
    print('\n')
        
# 创建一个单链表
def createLinkedlist(lst=[]):
    linkedlst = linkedList(lst[0])
    head = linkedlst
    p = head
    for _ in lst[1:]:
        node = linkedList(_)
        p.next = node
        p = node
    return head

# 在链表index处的结点后插入值为value的结点
def insert(index, head, value):
    count = 0
    p = head
    
    while p != None:
        if count == index:
            break
        else:
            p = p.next
            count += 1
    node = linkedList(value)
    node.next = p.next
    p.next = node
    
# 删除链表中所有值为value的结点
def delete(head, value):
    while head.data == value:            # 当头结点的值为value
        head = head.next
    
    pre = head
    q = pre.next
    while q != None:
        if q.data == value:
            pre.next = q.next
            q = q.next
        else:
            pre = q
            q = q.next
    return head

2. 用python实现循环单链表

class Recylelinkedlist:
    '''不带头结点的单循环链表'''
    def __init__(self, value, pnext=None):
        self.next = pnext
        self.data = value

# 创建一个带头结点单链表
def createRecyLinkedlist(lst=[]):
    recylinkedlst = Recylelinkedlist(lst[0])
    head = recylinkedlst
    p = head
    for _ in lst[1:-1]:
        node = Recylelinkedlist(_)
        p.next = node
        p = node
        
    node = Recylelinkedlist(lst[-1])  
    node.next = head
    p.next = node
    return head

def append(head, value):
    '''
    在尾结点后插入结点value
    '''
    p = head
    while p.next != head:    # 找到尾结点
        p = p.next
    node = Recylelinkedlist(value,head)
    p.next = node
    
def pop(head):
    '''删除单循环链表尾结点'''
    p = head
    while p.next.next != head:
        p = p.next
    p.next = head
    
def delFirst(head_node):
    '''删除头结点'''
    p = head_node
    while p.next != head_node:    # 找到尾结点
        p = p.next
    head = head_node.next
    p.next = head
    return head

# 在链表index处的结点后插入值为value的结点(若超过链表长度则继续循环往下数)
def insert(index, head, value):
    r = head
    count = 0
    while count != index:   # 找到index对应的结点
        r = r.next
        count += 1
        
    if r.next == head:    # 当目标位置刚好为尾结点位置
        node = Recylelinkedlist(value,head)
        r.next = node
    else:
        node = Recylelinkedlist(value)
        node.next = r.next
        r.next = node

# 删除链表中所有值为value的结点
def delete(head, value):
    while True:      # 若头结点的值为value
        if head.data == value:
            head = delFirst(head)
        else:
            break
            
    pre = head
    q = head.next
    while q != head:
        if q.data == value:
            pre.next = q.next
            q = q.next
        else:
            pre = q
            q = q.next
    return head

# 打印链表
def show(node):
    p = node
    while p.next != node:
        print(p.data, end = ' ')
        p = p.next
    print(p.data)      # 打印尾结点
    print('\n')

lst = [13,41,4,1,41,5,6]
head = createRecyLinkedlist(lst)
show(head)

append(head,10)
show(head)

head = delFirst(head)
show(head)

pop(head)
show(head)

insert(2, head, 99)
show(head)

head = delete(head, 41)
show(head)

3. 用python实现双向循环链表

class DoubleRecylelinkedlist:
    '''不带头结点的双向循环链表'''
    def __init__(self, value, pnext=None, ppre=None):
        self.next = pnext
        self.pre = ppre
        self.data = value

# 创建一个带头结点单链表
def createDoubleRecyLinkedlist(lst=[]):
    doubleRecylinkedlst = DoubleRecylelinkedlist(lst[0])
    head = doubleRecylinkedlst
    p = head
    for _ in lst[1:-1]:
        node = DoubleRecylelinkedlist(_)
        p.next = node
        node.pre = p
        p = node
        
    node = DoubleRecylelinkedlist(lst[-1])  
    node.next = head
    node.pre = p
    p.next = node
    head.pre = node
    return head

def append(head, value):
    '''
    在尾结点后插入结点value
    '''
    p = head.pre     # 尾结点
    node = DoubleRecylelinkedlist(value)
    p.next = node
    node.pre = p
    node.next = head
    head.pre = node
    
def pop(head):
    '''删除双循环链表尾结点'''
    p = head.pre.pre
    p.next = head
    head.pre = p
    
def delFirst(head_node):
    '''删除头结点'''
    p = head_node.pre             # 找到尾结点
    head = head_node.next
    head.pre = p
    p.next = head
    return head

# 在链表index处的结点后插入值为value的结点(若超过链表长度则继续循环往下数)
def insert(index, head, value):
    r = head
    count = 0
    while count != index:   # 找到index对应的结点
        r = r.next
        count += 1
        
    if r.next == head:    # 当目标位置刚好为尾结点位置
        node = DoubleRecylelinkedlist(value)
        r.next = node
        node.pre = r
        node.next = head
        head.pre = node
    else:
        node = DoubleRecylelinkedlist(value)
        node.next = r.next
        r.next.pre = node
        node.pre = r
        r.next = node

# 删除链表中所有值为value的结点
def delete(head, value):
    while True:      # 若头结点的值为value
        if head.data == value:
            head = delFirst(head)
        else:
            break
            
    pre = head
    q = head.next
    while q != head:
        if q.data == value:
            pre.next = q.next
            q.next.pre = pre
            q = q.next
        else:
            pre = q
            q = q.next
    return head

# 打印链表
def show(node):
    p = node
    while p.next != node:
        print(p.data, end = ' ')
        p = p.next
    print(p.data)      # 打印尾结点
    print('\n')

lst = [13,41,4,1,41,5,6]
head = createDoubleRecyLinkedlist(lst)
show(head)
print(head.data,head.pre.data,head.next.data)

append(head,10)
show(head)

head = delFirst(head)
show(head)

pop(head)
show(head)

insert(2, head, 99)
show(head)

head = delete(head, 41)
show(head)

4. python实现单链表反转

def reversedLinklist(linkedlist):
    r = linkedlist
    p = r.next
    r.next = None
    q = p
    p = p.next
    while q != None:
        q.next = r
        r = q
        q = p
        if p != None:
            p = p.next
    return r

5. python实现两个有序的链表合并为一个有序链表

def mergeSortLinkedlist(linkedlist1, linkedlist2):
    '''两个有序的不带头结点的链表合并为一个不带头结点的有序链表'''
    p = linkedlist1
    q = linkedlist2
    if q != None and p != None:
        if p.data <= q.data:
            head = p
            p = p.next
            head.next = None
        else:
            head = q
            q = q.next
            head.next = None
        r = head           # 创建头结点
        
        while q != None and p != None:
            if p.data <= q.data:
                r.next = p
                r = p
                p = p.next
            else:
                r.next = q
                r = q
                q = q.next
        if p:           # 若linkedlist1没有排序结束
            q = p
        r.next = q
        
    return head

6. python实现求链表的中间结点

def middleNode(linkedlist):
    p = linkedlist
    length = 0
    while p != None:
        length += 1
        p = p.next
    count = length // 2
    p = linkedlist
    while count:
        p = p.next
        count -= 1
    return p

7.LeetCode练习题

(1). Linked List Cycle I(环形链表)

class Solution(object):
    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        if head:
            while True:
                if head.val == 'vncbasdnvnvmz':
                    return True
                else:
                    head.val = 'vncbasdnvnvmz'
                    head = head.next
                    if head == None:
                        break
        return False

(2). Merge k Sorted Lists(合并 k 个排序链表)

采用思路:将链表转换为列表,对列表进行排序,再依据列表数据建立链表

执行用时 : 116 ms, 在Merge k Sorted Lists的Python提交中击败了84.19% 的用户
内存消耗 : 20.1 MB, 在Merge k Sorted Lists的Python提交中击败了11.89% 的用户

class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        if lists:
            re = []
            for lst in lists:
                if lst:
                    while lst:
                        re.append(lst.val)
                        lst = lst.next
            if re:
                re.sort()
                head = ListNode(re[0])
                r = head
                for value in re[1:]:
                    node = ListNode(value)
                    r.next = node
                return head

猜你喜欢

转载自blog.csdn.net/shichensuyu/article/details/90081395