Является ли отсортированный массив мини-кучей? Каково минимальное значение максимальной кучи?

Мне пришлось самому заниматься этим вопросом недавно. В конце концов, я использовал модификацию решения , предложенную Крисом МакКленагеном .

На самом деле его оригинальное решение довольно хорошо, и оно работает в самых простых случаях. Однако он работал только для меня на страницах с текстом. Вероятно, он также работает на страницах с изображениями, которые имеют статическую высоту. Однако это определенно не работает, если у вас есть изображения, размер которых определяется атрибутами max-height и max-width.

И это потому, что эти элементы могут быть изменены после загрузки страницы. Таким образом, высота, возвращаемая в onLoad, всегда будет правильной. Но это будет только верно для этого конкретного примера. Обходной путь - отслеживать изменение высоты body и отвечать на него.

Изменение размера монитора document.body

var shouldListenToResizeNotification = false
lazy var webView:WKWebView = {
    //Javascript string
    let source = "window.onload=function () {window.webkit.messageHandlers.sizeNotification.postMessage({justLoaded:true,height: document.body.scrollHeight});};"
    let source2 = "document.body.addEventListener( 'resize', incrementCounter); function incrementCounter() {window.webkit.messageHandlers.sizeNotification.postMessage({height: document.body.scrollHeight});};"

    //UserScript object
    let script = WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: true)

    let script2 = WKUserScript(source: source2, injectionTime: .atDocumentEnd, forMainFrameOnly: true)

    //Content Controller object
    let controller = WKUserContentController()

    //Add script to controller
    controller.addUserScript(script)
    controller.addUserScript(script2)

    //Add message handler reference
    controller.add(self, name: "sizeNotification")

    //Create configuration
    let configuration = WKWebViewConfiguration()
    configuration.userContentController = controller

    return WKWebView(frame: CGRect.zero, configuration: configuration)
}()

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    guard let responseDict = message.body as? [String:Any],
    let height = responseDict["height"] as? Float else {return}
    if self.webViewHeightConstraint.constant != CGFloat(height) {
        if let _ = responseDict["justLoaded"] {
            print("just loaded")
            shouldListenToResizeNotification = true
            self.webViewHeightConstraint.constant = CGFloat(height)
        }
        else if shouldListenToResizeNotification {
            print("height is \(height)")
            self.webViewHeightConstraint.constant = CGFloat(height)
        }

    }
}

Это решение на сегодняшний день является самым элегантным что я мог бы придумать. Есть, однако, две вещи, о которых вы должны знать.

Во-первых, перед загрузкой вашего URL-адреса вы должны установить shouldListenToResizeNotification на false. Эта дополнительная логика необходима для случаев, когда загруженный URL-адрес может быстро изменяться. Когда это происходит, уведомления из старого контента по какой-то причине могут пересекаться с сообщениями из нового контента. Чтобы предотвратить такое поведение, я создал эту переменную. Это гарантирует, что как только мы начнем загрузку нового контента, мы больше не будем обрабатывать уведомление из старого, и мы возобновим обработку уведомлений о размерах после загрузки нового контента.

Самое главное, однако, вы должны знать о это:

Если вы примете это решение, вам необходимо принять во внимание, что если вы измените размер вашего WKWebView на все, кроме размера, указанного уведомлением, уведомление будет снова запущено.

Будьте осторожны с этим, так как легко вводить бесконечный цикл. Например, если вы решите обработать уведомление, сделав высоту равной сообщаемой высоте + добавочное дополнение:

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        guard let responseDict = message.body as? [String:Float],
        let height = responseDict["height"] else {return}
        self.webViewHeightConstraint.constant = CGFloat(height+8)
    }

Как вы можете видеть, потому что я добавляю 8 к указанной высоте, после этого будет изменен размер моего body, и уведомление будет опубликовано снова.

Будьте внимательны к таким ситуациям, и в противном случае вы должны быть в порядке.

И, пожалуйста, дайте мне знать если вы обнаружите какие-либо проблемы с этим решением - я полагаюсь на него сам, поэтому лучше знать, есть ли некоторые ошибки, которые я не заметил!

13
задан nbro 29 July 2017 в 01:00
поделиться

2 ответа

При использовании реализации кучи на основе массивов массив, отсортированный от наименьшего к наибольшему, является минимальной кучей. Свойство кучи, что родительский узел больше, чем его дочерние узлы (2i + 1 и 2i + 2, при использовании массивов, основанных на нулях), действует для всех узлов, имеющих дочерние узлы.

Минимальное значение кучи max находится в одном из листовых узлов, но вы не знаете в каком. Поскольку минимальный узел по определению не может иметь дочерних узлов, он должен быть листом. Свойство кучи, однако, не определяет, как узлы листьев сравниваются друг с другом, только со своим родителем.

25
ответ дан 1 December 2019 в 20:11
поделиться

Является ли отсортированный массив минимальной кучей?

Да, если вы используете типичное соглашение о куче, хранящейся в массиве.

Где минимальное значение максимальной кучи?

На одном из листьев. Что точно не определено.

5
ответ дан 1 December 2019 в 20:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: