【问题标题】:Inserting a new item into an ascending ordered linked list将新项目插入升序链表
【发布时间】:2014-11-11 15:27:00
【问题描述】:

下面是我对 ASC 链表的插入方法的实现,它根据优先级将 PQueueItem 对象插入到 PQueueItem 类型的链表中。

我基本上检查看看,在优先级方面,如果要插入的项目大于当前项目并且小于下一个项目,如果是,则插入它。如果等于下一项,按字母顺序排列。如果它小于当前项,则将其放在它之前。如果它大于当前项和下一项,则遍历列表,直到满足其他检查之一。

这是实现插入的适当/有效方式吗?如果您认为我的想法两者兼而有之,那么非代码想法会很棒:

  1. 不正确
  2. 效率低下。

干杯!

public void insert(T data, int priority) {
        if(order == ORDER.ASC)
        {
            //current item
            PQueueItem<T> temp = head;

            while(temp.getNext() != null)
            {
                //is inserted item greater than current item
                if(priority > temp.getPriority())
                {
                    //is inserted item smaller than next item
                    if(priority < temp.getNext().getPriority())
                    {
                         //create and insert new item, reassign links in the list
                         PQueueItem<T> newPQ = new PQueueItem<T>(data, priority);
                         newPQ.setNext(temp.getNext());
                         temp.setNext(newPQ);

                    }
                    //check to see if priority equates to the next item's priority
                    else if(priority == temp.getNext().getPriority())
                    {
                        //is new item's data alphabetically greater than the next item's data
                        if(((String)data).compareToIgnoreCase((String)temp.getNext().getData()) > 0)
                        {
                             PQueueItem<T> nextPQ = temp.getNext();
                             PQueueItem<T> newPQ = new PQueueItem<T>(data, priority);
                             newPQ.setNext(nextPQ.getNext());
                             nextPQ.setNext(newPQ);
                        }
                        else
                        {
                            PQueueItem<T> newPQ = new PQueueItem<T>(data, priority);
                            newPQ.setNext(temp.getNext());
                            temp.setNext(newPQ);
                        }
                    }
                    else
                    {
                        //iterate current item
                        temp = head.getNext();
                    }
                } 
                //if item to be inserted is smaller than the current item
                else if(priority < temp.getPriority())
                {
                     PQueueItem<T> newPQ = new PQueueItem<T>(temp.getData(), temp.getPriority());
                     newPQ.setNext(temp.getNext());
                     temp.setData(data);
                     temp.setPriority(priority);
                }
            }
        }   
        else
        {
            //code for DESC             
        }
    }

【问题讨论】:

  • 如果这是一段工作代码,也许你的问题更适合SO Code Review。这里主要是关于“发现问题”之类的
  • 我不确定这是否可行,我只是将其作为一种可能的解决方案。对问题的措辞不佳表示歉意!
  • 如果您不确定它是否有效,您应该编写一些测试用例并对其进行编码;)
  • 你提出了一个有效的观点! ;)

标签: java linked-list


【解决方案1】:

吸引眼球的是:

  • 有一个虚拟头节点。

首先一个比较方法有意义:

private int compare(T data, int priority, PQueueItem<T> pq) {
    return -1 or 0 or 1;
}

然后没有一个虚拟节点作为头部:

    PQueueItem<T> prior = null;
    PQueueItem<T> current = head;

    // Walk to the insertion point:
    while (current != null) {
        int comparison = compare(data, priority, current);
        if (comparison >= 0) {
            if (comparison == 0) {
                return; // No insert?
            }
            break;
        }
        prior = current;
        current = current.getNext();
    }

    // Create the link:
    PQueueItem<T> newPQ = new PQueueItem<T>(data, priority);
    newPQ.setNext(current);

    if (prior == null) {
        head = newPQ;
    } else {
        prior.setNext(newPQ);
    }

【讨论】:

  • 所以在while循环中你会找到插入点和创建链接的代码无论如何都会发生,聪明!令人放心的是,您也使用了与我相同的技术。
【解决方案2】:

已经有一段时间了,但是有一些类似对数搜索的东西,它可以极大地提高您的实施速度(您现在与列表的大小成线性比例,对数与列表的大小成对数比例(理解这意味着什么,在 1000000000 个元素上,log(1000000000) 大约是 20,非常小)。

算法:从整个列表开始,然后将其切成两半。您要插入的元素恰好发生在这些半部分之一中。你选对了,也把它减半。您继续这样做,直到您查看的列表部分最多包含 2 个元素。然后你知道在哪里插入你的元素。实现通常是两个变量保存索引,并在每次迭代中将其中一个移动到您当前查看的一半。

每一步都会将要处理的元素减半,这意味着您最终会以最多对数复杂度的时间插入值。

另外,不要指望任何更好的解决方案,对数很难被击败。如果你想“即时”插入,你需要一个不同的结构。

【讨论】:

  • 这实际上叫做二分查找。 community.topcoder.com/…
  • 我的老师称之为对数,这个名字的准确性很难争论,但是,无论如何:D
  • BS 不适用于链表,因为每个元素都只有一个指向其后继元素的链接。因此要到达列表的末尾,唯一的方法就是遍历整个列表!因此 O(n)
  • 是的,这是真的。我认为可以肯定地说,没有办法扩大规模。您也许可以保存列表的检查点,这样您就可以“快速”遍历它们以查看最好从哪里开始搜索,但这根本不会降低时间复杂度。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-26
  • 1970-01-01
相关资源
最近更新 更多