Обмен переменных по индексам Связанный список python? - PullRequest
0 голосов
/ 04 февраля 2020

Я узнаю о LinkedLists, и я видел связанный ответ - но я не думаю, что это поможет мне в моей конкретной ситуации c: Обмен парами в связанном списке в Python, одна ссылка исчезает?

Однако у меня возникает аналогичная проблема, когда одна из моих переменных исчезает


class Node(object):
    def __init__(self,val):
        self.val = val
        self.next = None

    def get_data(self):
        return self.val

    def set_data(self,val):
        self.val = val

    def get_next(self):
        return self.next

    def set_next(self,next):
        self.next = next


class LinkedList(object):        

    def __init__(self,*values):
        self.count = len(values) -1
        self.head = Node(values[0])
        node = self.head
        for idx, val in enumerate(values):
            if idx == 0:
                continue
            else:
                tempnode = Node(val)
                node.set_next(tempnode)
                node = node.get_next()


    def get_count(self):
        return self.head

    def insert(self,data):
        new_node = Node(data)
        new_node.set_next(self.head)
        self.head = new_node
        self.count +=1

    def insert_at(self,idx,val):
        assert idx <= self.count +1

        if idx == 0:
            self.insert(val)
        else:
            tempIdx = 0
            node = self.head
            while tempIdx < idx -1:
                node = node.get_next()
                tempIdx += 1
            continuation = node.get_next()
            insertion = Node(val)
            node.set_next(insertion)
            node.get_next().set_next(continuation)

    def find(self,val):
        item = self.head
        while item != None:
            if item.get_data() == val:
                return item
            else:
                item = item.get_next()

        return None

    def deleteAt(self,idx):
        if idx > self.count-1:
            return
        if idx == 0:
            self.head = self.head.get_next()
        else:
            tempIdx = 0
            node = self.head
            while tempIdx < idx -1:
                node = node.get_next()
                tempIdx +=1
            node.set_next(node.get_next().get_next())
            self.count -= 1

    def dump_list(self):
        tempnode = self.head
        while (tempnode != None):
            print("Node: ",tempnode.get_data())
            tempnode = tempnode.get_next()

    def swap(self,idx_1,idx_2):
        if idx_1 == idx_2:
            pass
        elif idx_1 > idx_2:
            idx_b,idx_a = idx_1,idx_2
        else:
            idx_b,idx_a = idx_2,idx_1

        tempIdx = 0
        prev_node = None
        node = self.head
        while tempIdx < idx_a - 1:
#             print('while_a')
            prev_node = node
            node = node.get_next()
            tempIdx += 1

        try:
            prev_a = prev_node
            print('prev_a assigned')
        except:
            pass
        elem_a = node
        next_a = node.get_next()
        while tempIdx < idx_b -1:
#             print('while_b')            
            prev_node = node            
            node = node.get_next()
            tempIdx += 1
        prev_b = prev_node            
        elem_b = node
        try:
            next_b = node.get_next()
            print('next_b assigned')            
        except:
            pass

        try:
            prev_a.set_next(elem_b)
            print('prev_a.next assigned elem_b')            
        except:
            pass

        elem_b.set_next(next_a)
        prev_b.set_next(elem_a)
        try:
            elem_a.set_next(next_b)
            print('elem_a.next assigned next_b')            
        except:
            pass


Перейдите к методу класса, поменяйте местами. Это где проблема возникает, и вот мой вывод кода, когда я вызываю dum_list:


test = LinkedList(1,2,4)
test.insert_at(idx=2,val=3)
test.dump_list()
>>>> 
Node:  1
Node:  2
Node:  3
Node:  4

## so far, so good!

test.swap(1,2)
test.dump_list()
>>>>
Node:  1
Node:  3
Node:  4

Таким образом, узел со значением 2 удаляется. И я не уверен, где я иду не так ... В связанном вопросе, это голова, которая нуждается в обновлении. Но это не моя проблема, так как узел значения 2 - не голова.

Я принял конструктивную критику и довольно сильно изменил метод обмена; это работает сейчас!


    def swap(self,idx_a,idx_b):
        if idx_a == idx_b:
            return
        elif idx_a > idx_b:
            idx_2,idx_1 = idx_a,idx_b
        else:
            idx_2,idx_1 = idx_b,idx_a

        node = self.head
        tempIdx = 0

        while tempIdx < idx_2:
            if tempIdx != idx_1:
                node = node.get_next()
                tempIdx += 1
            else:
                elem_1 = node.get_data()
                node = node.get_next()
                tempIdx += 1
        elem_2 = node.get_data()

        self.deleteAt(idx_1)
        self.deleteAt(idx_2-1)
        self.insert_at(idx_1,elem_2)
        self.insert_at(idx_2,elem_1)

1 Ответ

2 голосов
/ 04 февраля 2020

Посмотрите на свой код подкачки; он не обрабатывает случай, когда a и b находятся рядом друг с другом: он беспечно предполагает, что ваши шесть указателей мест (prev | elem | next _ a | b) независимы. Пройдите логи c с бумагой и карандашом на вашем реальном случае. После мучительной локализации двух выбранных вами элементов у вас есть

prev_a         => None
elem_a, prev_b => 1
next_a, elem_b => 2
        next_b => 3

Теперь для вашего кода подкачки:

    prev_a.set_next(elem_b)

Это не работает тихо, и prev_a равно None; пока хорошо

    elem_b.set_next(next_a)

Node2.next теперь указывает на сам Node2

    prev_b.set_next(elem_a)

Node1.next теперь указывает на сам Node1.

    elem_a.set_next(next_b)

Node1.next теперь указывает на Node3.

Также обратите внимание, что head по-прежнему указывает на Node1, а не Node2.

Вы аккуратно отсоединили Node2 из списка; теперь у вас есть

head => Node1 => Node3 => Node4 => None
Node2 => Node2

Пройдите этот случай осторожно с карандашом и бумагой. Какой порядок изменений позволит вам поменять соседние узлы? Проблема здесь в том, что вам нужен Node2.next для ссылки на Node1, а не на исходный Node1.next.

Когда я брал структуры данных, мы тщательно проверяли местоположения и корректировали указатели с конца новый список , назад к началу. В этом случае мы сначала изменим Node1.next.

Обратите внимание, что вы также можете сделать это, удалив один узел и вставив его на другой стороне.


Я знаю это не полное решение; Надеюсь, этого достаточно, чтобы закончить ремонт самостоятельно. : -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...