链表在存储器中紧凑的排列

10.3-4    我们常常希望一个双链表中的所有元素在存储器中能够紧凑地排列在一起,例如使用多重数组表示中的前m个下标位置(在一个分页的虚拟计算机环境中情况就是这样)。假设链表以外没有指向链表元素的指针,请说明应如何实现过程ALLOCATE-OBJECT和FREE-OBJECT,才能使这种表示比较紧凑。(提示:使用栈的数组实现。)

 

分析与解答:

     假设链表中已有y个元素,并且已经紧凑排列。令top = y +1,表示下一个将要分配的指针位置

     在分配空间时很简单:

           ALLOCATE-OBJECT分配时,只需要top++,同时在双链表L的头部增加一个元素。

     在释放空间时稍微复杂:

          FREE-OBJECT释放时,若x和y相同,则只需要从双链表L中删除元素x,同时top--;若x<y,则需要将x删除,同时将元素y调整到x的位置,然后top--

 

整个过程如下:

 

  1. ALLOCATE-OBJECT()  
  2. y ← top[free]  
  3. if y > m  
  4.   then error "out of memory"  
  5. if head[L] ≠ NIL  
  6.   then prev[head[L]] = y  
  7. next[y] ← head[L]  
  8. prev[y] ← NIL  
  9. head[L] ← y  
  10. top[free] ← top[free]+1  
  11.   
  12. FREE-OBJECT(x)  
  13. y ← top[free]-1  
  14. if next[x] ≠ NIL  
  15.   then prev[next[x]] ← prev[x]  
  16. if prev[x] ≠ NIL  
  17.   then next[prev[x]] ← next[x]  
  18. else head[L] ← next[x]   
  19. prev[x] ← prev[y]  
  20. next[x] ← next[y]  
  21. key[x] ← key[y]  
  22. if prev[y] ≠ NIL  
  23.   next[prev[y]] ← x  
  24. if next[y] ≠ NIL  
  25.   prev[next[y]] ← x  
  26. top[free] ← top[free]-1  

10.3-5 设L是一长度为m的双链表,存储在长度为n的数组key、next和prev中。假设这些数组由维护双链自由表F的两个过程ALLOCATE-OBJECT和FREE-OBJECT来操纵。进一步假设在数组的n个元素中,有m个在表L和自由表F,移动L中的元素,使他们占有数组中的1, 2, ..., m位置,同时调节自由表F使之保持正确,并占有数组位置m+1, m+2, ..., n。所给出的运行时间应该是Θ(m),且只能使用固定量的额外空间。请仔细论证你所给出的过程的正确性。

 

分析与解答

      如下图所示,长度为m的双链表L存储在长度为n的数组中,自由表为F。为了使双链表分布更加紧凑,我们将移动L中的元素,使其占有数组中的1, 2, ..., m位置。

     我们可以采用交换的手法,将L中的第1个元素和数组第1个位置的元素进行交换,一次类推,L中的第m个位置的元素和数组的第m个元素进行交换,每次交换仅需要常量的额外空间。

 整个过程如下:

  1. COMPACTIFY-LIST(L, F)   
  2. x ← head[L]  
  3. num ← 0  
  4. while x ≠ NIL  
  5.   do num ← num+1  
  6.      if x ≠ num  
  7.        then SWAP-OBJECT(x, num)  
  8.      x ← next[x]  
  9. SWAP-OBJECT(i, j)  
  10. exchange A[i] ↔ A[j]  
  11. if prev[i] ≠ NIL  
  12.   then next[prev[i]] ← j  
  13. if next[i] ≠ NIL  
  14.   then prev[next[i]] ← j  
  15. if prev[j] ≠ NIL  
  16.   then next[prev[j]] ← i  
  17. if next[j] ≠ NIL  
  18.   then prev[next[j]] ← i  

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 线性链表在Java可以使用类来实现。具体来说,可以定义一个链表节点类,该类包括节点值和指向下一个节点的指针。然后,可以定义一个链表类,该类包括对链表头节点和链表尾节点的引用,以及一些方法来操作链表,例如添加节点、删除节点和遍历节点等。以下是一个示例代码: ``` public class ListNode { int val; ListNode next; ListNode(int x) { val = x; next = null; } } public class LinkedList { ListNode head; ListNode tail; public LinkedList() { head = null; tail = null; } public void addNode(int val) { ListNode newNode = new ListNode(val); if (head == null) { head = newNode; tail = newNode; } else { tail.next = newNode; tail = newNode; } } public void deleteNode(int val) { if (head == null) { return; } if (head.val == val) { head = head.next; return; } ListNode prev = head; ListNode curr = head.next; while (curr != null) { if (curr.val == val) { prev.next = curr.next; if (curr == tail) { tail = prev; } return; } prev = curr; curr = curr.next; } } public void printList() { ListNode curr = head; while (curr != null) { System.out.print(curr.val + " "); curr = curr.next; } } } ``` 使用这些类,可以轻松地创建和操作线性链表。例如,可以创建一个新的链表对象,向其添加节点,删除节点,以及遍历链表并打印每个节点的值。 ### 回答2: 线性链表是一种常见的数据结构,它在Java的应用非常广泛。 首先,线性链表可以用来实现动态数据的存储和管理。在Java,数组的长度是固定的,而线性链表可以根据需要动态地添加、删除和修改数据。这使得线性链表特别适合在需要频繁增删数据的场景使用,如链表可以用来实现队列和栈等数据结构。 其次,线性链表可以用来实现数据的排序和查找。虽然数组也可以实现排序和查找功能,但是对于需要频繁插入和删除数据的场景,数组的性能通常不如链表。通过使用链表,可以快速插入和删除元素保持数据的有序性,同时也可以通过遍历链表来查找特定元素。 此外,线性链表还可以用于实现Java的一些常用类库。例如,Java的LinkedList类就是基于线性链表的实现,它提供了一些方便的方法来操作链表。此外,线性链表还可以用于实现一些其他的数据结构,如图和树等。 总之,线性链表在Java有着广泛的应用。它的动态性、灵活性和可扩展性使得它成为了许多问题的解决方案。无论是处理动态数据还是实现高效的数据结构,线性链表都是一个非常有用的选择。 ### 回答3: 线性链表是一种常用的数据结构,它在Java也得到广泛的运用。 在Java,线性链表通常通过LinkedList类来实现。LinkedList类是Java集合框架的一部分,它提供了一种有序的、可以动态改变大小的链表。 通过LinkedList类,我们可以进行各种操作,比如添加元素、删除元素、查询元素等。具体而言,LinkedList类提供了一系列的方法,例如add()、remove()、get()等,通过这些方法,我们可以对链表进行增删改查的操作。 线性链表在Java的运用非常广泛。例如,我们可以使用线性链表来实现队列和栈等数据结构。通过使用线性链表,我们可以轻松地实现这些数据结构的操作,比如入队、出队、入栈、出栈等。 此外,线性链表还可以用于解决一些具体的问题。例如,我们可以使用线性链表来实现约瑟夫环问题,通过不断的删除元素,最终找到最后剩下的元素。 总之,在Java,线性链表是一种常用的数据结构,通过LinkedList类的运用,我们可以方便地对线性链表进行各种操作,解决各种实际问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值