ListNode *reverseKGroup(ListNode *head, int k) { if (head == NULL || head->next == NULL || k <= 1) return head; ListNode *currStart, *currEnd; ListNode *nextStart, *prevEnd; ListNode emptyNode(0); prevEnd = &emptyNode; currStart = head; while (currStart) { currEnd = currStart->next; for (int i = 2; currEnd && i < k; i++) currEnd = currEnd->next; if (currEnd == NULL) break; nextStart = currEnd->next; reverseGroup(currStart, k); prevEnd->next = currEnd; prevEnd = currStart; currStart->next = nextStart; currStart = nextStart; } return emptyNode.next ? emptyNode.next : head; }
Node *HashLife::emptyNode(size_t depth) { if (depth >= static_cast<size_t>(m_emptyNode.size())) { Node *sub = emptyNode(depth - 1); Node *node = m_nodeHash->get(sub, sub, sub, sub); m_emptyNode.push_back(node); return node; } else return m_emptyNode[depth]; }
void HashLife::expand() { Node *e = emptyNode(m_depth - 1); Node *nul = m_nodeHash->get(e, e, e, m_root->ul); Node *nur = m_nodeHash->get(e, e, m_root->ur, e); Node *ndl = m_nodeHash->get(e, m_root->dl, e, e); Node *ndr = m_nodeHash->get(m_root->dr, e, e, e); m_root = m_nodeHash->get(nul, nur, ndl, ndr); BigInteger offset = BigInteger::exp2(m_depth - 1); m_x -= offset; m_y -= offset; m_depth++; }
void HashLife::run() { QTime timer; timer.start(); m_running = true; m_writeLock->lock(); m_readLock->lock(); while (m_increment + 2 > m_depth) expand(); Node *e = emptyNode(m_depth - 2); // Test boundary to be empty, or we have to expand() to guarantee the result fits in the boundary // This requires m_depth to be at least Block::DEPTH + 2 if ((m_root->ul->ul != e || m_root->ul->ur != e || m_root->ul->dl != e) || (m_root->ur->ul != e || m_root->ur->ur != e || m_root->ur->dr != e) || (m_root->dl->ul != e || m_root->dl->dl != e || m_root->dl->dr != e) || (m_root->dr->ur != e || m_root->dr->dl != e || m_root->dr->dr != e)) expand(); // To make the depth of RESULT equal to m_depth, we first expand the universe // This is nearly identical to code in expand() except we don't need to touch m_x and m_y e = emptyNode(m_depth - 1); Node *nul = m_nodeHash->get(e, e, e, m_root->ul); Node *nur = m_nodeHash->get(e, e, m_root->ur, e); Node *ndl = m_nodeHash->get(e, m_root->dl, e, e); Node *ndr = m_nodeHash->get(m_root->dr, e, e, e); Node *nroot = m_nodeHash->get(nul, nur, ndl, ndr); m_readLock->unlock(); Node *new_root = runNode(nroot, m_depth + 1); m_readLock->lock(); m_root = new_root; m_readLock->unlock(); m_writeLock->unlock(); m_generation += BigInteger::exp2(m_increment); m_running = false; emit gridChanged(); qDebug() << timer.elapsed(); }
HashLife::HashLife() : m_readLock(new QMutex()), m_writeLock(new QMutex()), m_running(false), m_blockHash(new HashTable<Block, uchar>()), m_nodeHash(new HashTable<Node, Node *>()), m_x(0), m_y(0), m_generation(0) { m_increment = 0; // TODO Node *e = reinterpret_cast<Node *>(m_blockHash->get(0, 0, 0, 0)); m_emptyNode.resize(Block::DEPTH + 1); for (size_t i = 0; i < Block::DEPTH; i++) m_emptyNode[i] = NULL; m_emptyNode[Block::DEPTH] = e; m_root = emptyNode(Block::DEPTH + 1); m_depth = Block::DEPTH + 1; expand(); // run() requires m_depth >= Block::DEPTH + 2 }
void HashLife::paint(CanvasPainter *painter, const BigInteger &x, const BigInteger &y, int w, int h, size_t scale) { m_readLock->lock(); treePaint<HashLife, Block, Node>(this, painter, x, y, w, h, scale, m_x, m_y, m_depth, m_root, emptyNode(m_depth)); m_readLock->unlock(); }