一个python实现的有魔法方法(magic method)的单链表(静态链表)

做题要用到单链表,就实现了一个静态单链表,别管性能怎么样,能用就行。

为了方便,加入了一些魔法函数,使得它可以像list那样使用索引功能切片功能和for循环。

链表的node是一个二元的list,第一个元素是数据,第二个元素是下一个node的下标。

链表可以自动增长长度,一开始是8,每次翻一倍。

链表内部的那个list的头两个节点分别是空闲头结点和非空闲头结点。

向链表里增加数据有很多种方法,在示例里演示了4种,就是这一行的四种方法。

依次是初始化,函数,头插,尾添。

LinkList([7, 8])(range(3)).insert(6).append(5)

但实际上只有两个,一个头插,一个尾添。初始化和函数都是调用的append,所以都是尾添。

另外还可以使用赋值来增加新元素,但是没有实现完该功能,目前只能给某一个节点赋值。

删除也是没有实现完,只能删除某一个节点,如del ll[4]这样。


代码如下

# -*- coding: cp936 -*-
'''
这是一个静态单链表的实现
同时实现了一些magic method用于进行iter或者slice等等
需要注意的是,代码中的游标(指针)和key不是同一个概念
cur(pointer)是这个静态链表元素的实际下标
key是这个单链表元素的逻辑下标

未完,以后再写吧,写了一上午了,有些懒
2017.03.10
平善明
'''


class LinkList():
    # a linklist implement by list with static
    # 2017.03.10
    # psm
    def __init__(self, li=[]):
        self.size = 10  # the real size of ll
        self.li = [[None, i + 1] for i in range(self.size)]  # allocate
        self.li[self.size - 1][1] = None  # the tail point None
        self.li[0][0] = self.size - 2  # the length of unused space
        self.li[0][1] = 2  # the pointer to the first unused space
        self.li[1][0] = 0  # the length of ll(used space)
        self.li[1][1] = None  # the pointer to the first used space

        if li != []:  # add the items to the ll
            self(li)
    def insert(self, x):
        # insert x at the begining of the LinkList
        if self.li[0][0] < 1:
            self.expandSize()  # if no space,expand the ll
        nullCur = self.li[0][1]  # the pointer to the first unused space
        self.li[0][0] -= 1  # unused space minus one
        self.li[1][0] += 1  # used space add one
        self.li[0][1] = self.li[nullCur][1]  # move unused pointer
        self.li[nullCur][0] = x  # give the value to the new item
        self.li[nullCur][1] = self.li[1][1]
        self.li[1][1] = nullCur  # head link new node
        return self
    def append(self, x):
        # insert x at the end of the LinkList
        if self.li[0][0] < 1:
            self.expandSize()  # if no space,expand the ll
        tail = 1
        while self.li[tail][1] != None:
            tail = self.li[tail][1]  # get the tail of ll
        nullCur = self.li[0][1]  # the pointer to the first unused space
        self.li[0][0] -= 1  # unused space minus one
        self.li[1][0] += 1  # used space add one
        self.li[0][1] = self.li[nullCur][1]  # move unused pointer
        self.li[nullCur][0] = x  # give the value to the new item
        self.li[nullCur][1] = self.li[tail][1]  # new node become tail
        self.li[tail][1] = nullCur  # old tail link new tail
        return self
    def delete(self, delCur):
        self.li[1][0] -= 1  # used space minus one
        self.li[0][0] += 1  # unused space add one
        self.li[delCur][0] = None  # del the value
        cur = 1
        while self.li[cur][1] != delCur:
            cur = self.li[cur][1]  # get the ahead pointer
        self.li[cur][1] = self.li[delCur][1]  # the ahead pointer link the hinder item
        self.li[delCur][1] = self.li[0][1]  # add the item to unused list
        self.li[0][1] = delCur
        return self
    def expandSize(self):
        self.li[0][1] = self.size
        self.li += [[None, self.size + i + 1] for i in range(self.size - 2)]
        self.li[-1][1] = None
        self.li[0][0] = self.size - 2
        self.size = len(self.li)
    def pHead(self):
        return self.li[1][1]
    def empty(self):
        return self.li[1][0] == 0
    def length(self):
        return self.li[1][0]
    def printUsed(self):
        for i in self:
            print i,
        print
        return self
    def printUnused(self):
        ncur = self.li[0][1]
        while ncur is not None:
            print self.li[ncur],
            ncur = self.li[ncur][1]
        print
        return self

    # cur(or pointer,p) is the index in self.li
    # key is the logical location
    #    [[2, 8], [6, 2], [0, 4], [1, 5], [2, 3], [3, 6], [4, 7], [6, None], [None, 9], [None, None]]
    # cur     0       1      2       3       4       5       6        7        8           9
    # key                    0       2       1       3       4        5
    def getPointerOfKey(self, key):
        # as title,the key is int
        if key < self.length():
            if key >= 0:
                num = 0
                p = self.pHead()
                while num != key:
                    p = self.li[p][1]
                    num += 1
                return p
            elif key < 0 and key > -self.length():
                p0, p1 = self.pHead(), self.pHead()
                for i in range(-key):
                    p1 = ll.li[p1][1]
                while p1 is not None:
                    p0 = ll.li[p0][1]
                    p1 = ll.li[p1][1]
                return p0
            else:
                raise KeyError('no this key\n')
        else:
            raise KeyError('no this key\n')
    def reorganizeSliceKey(self, key):
        # [::]->
        # [::1]->[0:len(self):1]
        # [::-1]->[len(self)-1:-1:-1]
        # [1:]->[1:len(self):1]
        start, stop, step = key.start, key.stop, key.step
        # print start, stop, step
        if key.stop == 9223372036854775807L:
            stop = len(self)
        if start is None and stop is None:
            if step is None:
                print 'haven"t implement'
                return None
            elif step > 0 :
                start = 0
                stop = len(self)
            else:
                start = len(self) - 1
                stop = -1
        if step is None:
            step = 1
        return start, stop, step
    def __len__(self):
        return self.li[1][0]
    def __iter__(self):
        self.ncur = self.li[1][1]  # next item's index
        return self
    def next(self):
        if self.ncur is not None:
            ret = self.li[self.ncur]
            self.ncur = self.li[self.ncur][1]
            return ret
        else:
            raise StopIteration
    def __getitem__(self, key):
        if isinstance(key, int):
            return self.li[self.getPointerOfKey(key)]
        elif isinstance(key, slice):
            start, stop, step = self.reorganizeSliceKey(key)
            # return a new ll
            return LinkList([self.__getitem__(i)[0]
                             for i in range(start, stop, step)])
        else:
            raise TypeError('key must be int or slice\n')
    def __setitem__(self, key, value):
        # one -> one : change the value
        # one -> many : del it, and add new item at this location
        # many -> one : change the first value, del others
        # little -> many : del them, and add new item at this location
        # many -> little : change the ahead values, del others
        if isinstance(key, int):  # one ->
            if not (isinstance(value, list) or isinstance(value, tuple)):  # one -> one
                self.li[self.getPointerOfKey(key)][0] = value
            else:  # one -> many
                pass
        elif isinstance(key, slice):  # many ->
            start, stop, step = key.start, key.stop, key.step
            print start, stop, step
            print 'haven"t implement'
            return None
        else:
            raise TypeError('key must be int or slice\n')
    def __delitem__(self, key):
        # del one
        # del many
        if isinstance(key, int):
            self.delete(self.getPointerOfKey(key))
        elif isinstance(key, slice):
            start, stop, step = key.start, key.stop, key.step
            print start, stop, step
            print 'haven"t implement'
            return None
        else:
            raise TypeError('key must be int or slice\n')
    def __call__(self, li):
        if isinstance(li, list) or isinstance(li, tuple):
            for i in li:  # add all item in li to the LinkList
                self.append(i)
        else:
            self.append(li)  # add item to the LinkList
        return self
    def __reversed__(self):
        pass
    def __contains__(self, item):
        pass

if __name__ == '__main__':
    print '\ninit:'
    ll = LinkList([7, 8])(range(3)).insert(6).append(5).printUsed()

    print '\nall space:'
    print ll.li

    print '\nindex:', ll[-1], ll[0], ll[1]

    print '\nslice:'
    ll[:].printUsed()
    ll[::-1].printUsed()
    ll[1:3].printUsed()
    ll[4:0:-1].printUsed()

    print '\nassignment:'
    ll[3] = 9
    ll[-2] = 'a'
    ll.printUsed()

    print '\ndel:'
    del ll[2]
    del ll[-2]
    ll.printUsed()

    print '\niter:'
    for i in ll:
        print i,
    print

运行结果示例:

init:
[6, 2] [7, 3] [8, 4] [0, 5] [1, 6] [2, 8] [5, None]

all space:
[[1, 9], [7, 7], [7, 3], [8, 4], [0, 5], [1, 6], [2, 8], [6, 2], [5, None], [None, None]]

index: [5, None] [6, 2] [7, 3]

slice:
[6, 3] [7, 4] [8, 5] [0, 6] [1, 7] [2, 8] [5, None]
[5, 3] [2, 4] [1, 5] [0, 6] [8, 7] [7, 8] [6, None]
[7, 3] [8, None]
[1, 3] [0, 4] [8, 5] [7, None]

assignment:
[6, 2] [7, 3] [8, 4] [9, 5] [1, 6] ['a', 8] [5, None]

del:
[6, 2] [7, 4] [9, 5] [1, 8] [5, None]

iter:
[6, 2] [7, 4] [9, 5] [1, 8] [5, None]



阅读更多
个人分类: python 数据结构
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭