Estrutura de dados consultável eficiente para representar uma tela com janelas

7

(isso está relacionado à minha outra pergunta, veja aqui )

Imagine uma tela com três janelas:

insira a descrição da imagem aqui

Gostaria de encontrar uma estrutura de dados eficiente para representar isso, apoiando essas ações:

  • retornar uma lista de coordenadas onde uma determinada janela pode ser posicionada sem se sobrepor a outras
    • para o exemplo acima, se quisermos inserir uma janela de tamanho 2x2, as possíveis posições serão (8, 6), (8, 7), ..
  • redimensionando uma janela na tela sem sobrepor outras, mantendo a proporção
  • insira a janela na posição x, y (assumindo que não se sobrepõe)

No momento, minha abordagem ingênua é manter uma variedade de janelas e examinar todos os pontos da tela, verificando cada uma delas em alguma das janelas. Isto éO(nmW) Onde n,m são a largura, altura da tela e Wé o número de janelas nele. Note que em geralW será pequeno (digamos <10), onde cada janela está ocupando muito espaço.

daniel.jackson
fonte
Por curiosidade, por que você precisa do conjunto de pontos? Se for para resolver outro problema, pode haver uma abordagem fundamentalmente melhor. Se não houver janelas, ainda não seráO(nm)construir a solução, ou seja, todos os pontos no retângulo vermelho? Como você deseja representar o conjunto de pontos?
precisa saber é o seguinte
@ Patrick87: Você está correto, e talvez eu esteja abordando isso na direção errada. Vou editar a pergunta.
Daniel.jackson

Respostas:

3

Uma otimização fácil para o algoritmo ingênuo é pular alguns pontos quando você verifica um coberto por uma janela. Digamos que você digitalize da esquerda para a direita, de cima para baixo. Se você encontrar um(x,y) na janela W=(eu,r,W,h), você pode pular de x para eu+W+1 1E continue. Se as janelas são grandes e não se sobrepõem, eu desconfio muito que lhe daria umaO(p) algoritmo, onde p é o número de pontos no conjunto que você retorna.

De fato, pode ser benéfico verificar se as janelas são geralmente mais largas ou mais altas. Para janelas altas, seria melhor escanear de cima para baixo, da esquerda para a direita; para janelas amplas, o método discutido acima deve vencer. Você pode ter a ideia e fazer a varredura / pular na diagonal para obter um desempenho equilibrado.

De fato, ao digitalizar da esquerda para a direita, de cima para baixo, você pode se lembrar de h linhas (valores de y) que você precisará pular ao mesmo x valor para o mesmo eu+W+1 1 valor, se você atingir o x(talvez não, se houver outra janela sobreposta). Isso tornaria a digitalização de cima para baixo, da esquerda para a direita e na diagonal desnecessária para obter um desempenho equivalente.

De maneira mais geral, agora você tem duas estruturas de dados: uma com O(1 1) despesas gerais de pré-processamento / construção e O(W) pesquisas e uma com O(p) (possivelmente; talvez você possa fazer melhor, ou talvez minha otimização realmente não atinja isso) pré-processamento / construção e possivelmente O(1 1) (tabela de hash / pesquisa) ou O(registrop)(BST). Portanto, já existem duas alternativas, ambas muito boas, realmente ...

Patrick87
fonte
Como você alcançaria o que descreveu no terceiro parágrafo? No momento, implementei sua primeira sugestão, examinando todas as janelas e, se houver uma sobreposição, pulo. Isso é executado em um loop até que a coordenada (x, y) da janela atual que estou tentando ajustar não seja alterada em uma única iteração.
Daniel.jackson
Talvez mantenha uma tabela de hash (contador y, esquerda, direita) triplica com o elemento do meio que determina o hash; adicione um e inicialize para (y + h, x - 1, l + w + 1) quando você bate em um retângulo; verifique a tabela antes de digitalizar através de retângulos; se y> y_max, ignore e remova; algo assim, talvez.
precisa saber é o seguinte