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

来源:互联网 发布:网络西瓜是什么意思啊 编辑:程序博客网 时间:2024/05/22 05:12

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

为了方便,加入了一些魔法函数,使得它可以像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):        passif __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]



0 0
原创粉丝点击