python 关于循环链表的实现 - 从哪里倒下,就从哪里站起来

问题:

循环链表的检查

构造一个单向循环链表。

输出是否有循环,循环的长度,开始循环的节点。

例:

a-b-c-d-e-f-g-h-i-j-k-l-m-n-e

有循环e-f-g-h-i-j-k-l-m-n-e

循环长度为10

开始循环的节点为e

解决方案:

在头节点前增加一个空节点,便于一致性处理。

采用两个变量x, y从空节点开始分别遍历该链表。

变量x按顺序遍历每一个节点。

变量y按顺序隔一个节点遍历一次。

x和y同时指向同一个节点,则有循环。

x和y再次相遇时,x遍历的节点就是循环的长度。

用一个数组存储x所有遍历过的节点,倒序搜索,找到不在循环中的节点。该节点的下一个节点就是循环的开始节点。

讨论:

当链表很大时,存储路径的数组需要比较大,耗资源。

源代码:

# coding=utf-8
import re
import os
import time
from datetime import datetime

def test_jump_to(n):
    '''跳转表'''
    return {
        1: test_dict_item, # 只是函数名,不能带小括号
        2: test_str,
        3: test_time_format,
        4: do_loop_link_list
    }.get(n, test_default)

class link_node():
    def __init__(self, node_value, node_next=None):
        # type: (object, object) -> object
        self.node_value = node_value
        self.node_next = node_next

class do_loop_link_list():
    def __init__(self, list_num, loop_position):
        self.list_num = list_num
        self.loop_position = loop_position
        self.list_value = ['%s' % chr(i) for i in range(65, 65+self.list_num, 1)]
        # ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N']
        print(self.list_value)

        self.link_node0 = link_node('')  # 在头结点前加入空节点
        for i in range(1, self.list_num+1, 1):
            node_name_pre = 'link_node' + '{num}'.format(num=i-1)
            node_name = 'link_node' + '{num}'.format(num=i)
            node_value = self.list_value[i-1]
            exec ('self.' + node_name + '=link_node(node_value)') # self.link_node1 = link_node('A')
            exec ('self.' + node_name_pre + '.node_next' '=self.' + node_name) # self.link_node0.node_next = self.link_node1

        self.show_link_list()
        self.create_loop(self.loop_position)
        self.show_link_list()

    def show_link_list(self):
        node = self.link_node0
        list_len = 0
        if False == self.has_loop():
            while(1):
                list_len += 1
                if node.node_next == None:
                    break
                node = node.node_next
            print('\n链表(无循环)长度为:%d' % list_len)
        else:
            print('\n链表存在循环')

    def create_loop(self, loop_position):
        node = self.link_node0
        node_list = []
        if False == self.has_loop():
            while (1):
                if node.node_next == None:
                    node.node_next = node_list[loop_position]
                    node_list.append(node.node_next)
                    break
                node = node.node_next
                node_list.append(node)
        print(('\n设置开始循环的节点位置为:%d 取值为:%s') % (loop_position, node_list[loop_position].node_value))
        for node in node_list:
            print(node.node_value),

    def has_loop(self):
        flag = 0
        loop_len = 0
        rec_list = [] # 记录x的轨迹
        node_x = self.link_node0
        node_y = self.link_node0
        while(1):
            rec_list.append(node_x)
            if node_x.node_next == None or node_y.node_next == None:
                break
            elif node_y.node_next.node_next == None:
                break
            else:
                node_x = node_x.node_next
                node_y = node_y.node_next.node_next
                if node_x == node_y:
                    flag += 1
            if flag == 1:   # 第一次相遇时开始计数
                loop_len += 1
            elif flag == 2: # 再次相遇时退出
                print('\n循环长度为:%d' % loop_len)
                break

        if flag == 2:
            rec_list.pop(0)
            for i in range(0, len(rec_list), 1):
                if rec_list[i].node_value == rec_list[i + loop_len].node_value:
                    print(('\n开始循环的节点位置:%d 取值为:%s') % (i, rec_list[i].node_value))
                    break

        return True if flag else False

def test_default():
    print('hello')
    s = 'abc'
    exec(s+'=5')
    print(abc)

def test_time_format():
    print(datetime.now())
    s = '2015-12-21 15:01:28'
    time_s = datetime.strptime(s, "%Y-%m-%d %H:%M:%S")
    print(time_s)

def test_dict_item():
    '''测试字典的 itemsiteritemsviewitems三个属性'''
    b = {'a':1,'b':2,'c':3}
    bi = b.items()      # v3版本统一
    bii = b.iteritems() # v3版本取消
    bvi = b.viewitems() # v3版本兼容
    print(bi)
    print(bii)
    print(bvi)
    for key, value in bii:
        print('bii',key,value)
    for key, value in bvi:
        print('bvi', key, value)
    print('*******************')
    b['d']=4
    print(bi)
    print(bii)
    print(bvi)
    for key, value in bii:
        print('bii', key, value)
    for key, value in bvi:
        print('bvi', key, value)

def test_str():
    str0 = 'nihao "hello" hi'
    print(str0)
    str1 = "nihao \"hello\" hi"
    print(str1)
    dict0 = {'a': 1, 'b': 2, 'c': 3}
    str2 = 'a=%(a)s,b=%(b)s,c=%(c)s' % dict0  # % 小括号
    str3 = 'a={a},b={b},c={c}'.format(a=1, b=2, c=3)  # format 大括号
    print(str2)
    print(str3)
    str4 = ('adfad'
            'agdf')
    print(str4)

if '__main__' == __name__:
    test_jump_to(4)(18,8)
'''
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R']
链表(无循环)长度为:19
设置开始循环的节点位置为:8 取值为:I
A B C D E F G H I J K L M N O P Q R I
循环长度为:10
开始循环的节点位置:8 取值为:I
链表存在循环
'''




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值