自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

聊聊堆Heap和二叉堆的實現(xiàn)和特性

數(shù)據(jù)庫
堆本身是一個相對比較抽象的數(shù)據(jù)結構,那么它有具體的實現(xiàn)就分為二叉堆(二項堆、Binary)、裴波那契堆(基于樹的)。那么要實現(xiàn)的話一般面試來說或者經(jīng)常會用的話就是二叉堆來實現(xiàn),當然在工業(yè)級比較牛逼的應用都是裴波那契以及非常嚴格裴波那契。裴波那契堆因為相對比較復雜,你可以不知道去怎么實現(xiàn),但是你可以看它的時空復雜度更好,它的實現(xiàn)也是基于樹,但是并不少二叉樹而是多叉的。

[[353560]]

 堆 Heap

Heap:可以迅速找到一堆數(shù)中的最大或者最小值的數(shù)據(jù)結構。

將根節(jié)點最大的堆叫做大頂堆或大根堆,根節(jié)點最小的堆叫做小頂堆或小根堆。

常見的堆有二叉堆、裴波那契堆等。

堆本身是一個相對比較抽象的數(shù)據(jù)結構,那么它有具體的實現(xiàn)就分為二叉堆(二項堆、Binary)、裴波那契堆(基于樹的)。那么要實現(xiàn)的話一般面試來說或者經(jīng)常會用的話就是二叉堆來實現(xiàn),當然在工業(yè)級比較牛逼的應用都是裴波那契以及非常嚴格裴波那契。裴波那契堆因為相對比較復雜,你可以不知道去怎么實現(xiàn),但是你可以看它的時空復雜度更好,它的實現(xiàn)也是基于樹,但是并不少二叉樹而是多叉的。

假設是大頂堆,則常見操作(API):

  • find-max:O(1)
  • delete-max:O(logN)
  • insert(create):O(logN) or O(1)

“堆” 這種數(shù)據(jù)結構為什么會有用? 在很多線上中的情形經(jīng)常會在使用,比如說經(jīng)常一個數(shù)一個數(shù)的過來,同時還有從另外一邊的化經(jīng)常去刪除一些數(shù)據(jù),問你這些數(shù)據(jù)里面它最大值是多少?這里的最大值可能就代表優(yōu)先級最高的結點或者是那個數(shù)需要你先處理的,比如說你的任務流里面隨時你要拿出優(yōu)先級最高的任務優(yōu)先處理,那么這種數(shù)據(jù)結構就更加的好用。

有些人可能會想我用數(shù)組來實現(xiàn)可不可以?或者是我直接排序可不可以?這里我們可以思考一下: 假設維護一個數(shù)組,每次有個新元素插入進來,你就需要把整個數(shù)組進行一次所謂的排序,這樣的話時間復雜度就會是 nlogn,這樣的話就是不夠高效的,另外刪除也可能比較麻煩,假設刪除的是最大值或最小值在最后面的話還好,可以是 O(1) 的時間復雜度,但是如果在最前面的話,你就必須把整個數(shù)組最前面元素刪除掉之后,把整個數(shù)組往前挪,這樣時間復雜度又變差了。

不同的實現(xiàn)比較:https://en.wikipedia.org/wiki/Heap_(data_structure)


當你提到“堆” 的時候,不要默認認為是二叉堆,同時你要知道堆的實現(xiàn)又很多種,而二叉堆本身的話只是因為它相對比較容易實現(xiàn),它的時間效率是堆里面算比較差的。

二叉堆的性質

通過完全二叉樹來實現(xiàn)(注意:不是二叉搜索樹);

什么是完全二叉樹? 就是它的根和每一級結點都是滿的,除了最下面一層葉子結點可能不滿之外,其他上面結點都是滿的。

二叉堆(大頂)它滿足下列性質:

  • 性質1:是一顆完全樹;
  • 性質2:樹中任意結點的值總數(shù) >= 其子節(jié)點的值;

 

由于性質2,就可以保證根結點是最大的結點,所以我們訪問最大值就直接返回這個根結點值。這里思考一個問題:為什么要做成樹的結構呢?其實就要方便,因為找最大值是O(1)了是滿足的,但是問題是后續(xù)你要刪除一個元素或者你要添加一個元素,怎么讓這個操作高效,至少是 logn 的。

二叉堆的實現(xiàn)細節(jié)

  1. 二叉堆一般都通過 “數(shù)組” 來實現(xiàn)
  2. 假設“第一個元素” 在數(shù)組中的索引為 0 的話,則父結點和子結點的位置關系如下:索引為 i 的左孩子的索引是 (2∗i+1);索引為 i 的右孩子的索引是 (2∗i+2);索引為 i 的父結點的索引是 floor((i−1)/2);

因為把一個完全二叉樹依次放到一維數(shù)組里面去,那么它的孩子和父親之間的關系,就可以直接用下班的數(shù)學關系表示了。

 

Insert 插入操作

  1. 新元素一律先插入到堆的尾部
  2. 依次向上調整整個堆的結構(一直到根即可) HeapifyUp

當這個堆要進行維護操作,也就是插入元素的時候以及你要刪除元素的時候要怎么做?

例子:85 添加到二叉堆中

 操作的細節(jié)分為兩步:

  • 第一步:首先把新元素插入到堆的尾部再說;(新的元素可能是特別大或者特別小,那么要做的一件事情就是重新維護一下堆的所有元素,把新元素挪到這個堆的相應的位置)
  • 第二步:依次向上調整整個堆的結構,就叫 HeapifyUp

85 按照上面講的先插入到堆的尾部,也就是一維數(shù)組的尾部,一維數(shù)組的尾部的話就上圖的位置,因為這是一個完全二叉樹,所以它的尾部就是50后面這個結點。插進來之后這個時候就破壞了堆,它的每一個結點都要大于它的兒子的這種屬性了,接下來要做的事情就是要把 85 依次地向上浮動,怎么浮動?就是 85 大于它的父親結點,那么就和父親結點進行交換,直到走到根如果大于根的話,就和根也進行交換。


85 再繼續(xù)往前走之后,它要和 80 再進行比較,同理可得:也就是說這個結點每次和它的父親比,如果它大于它的父親的話就交換,直到它不再大于它的父親。 

 

Delete Max 刪除堆頂操作

將堆尾元素替換到頂部(即堆頂被替代刪除掉)

依次從根部向下調整整個堆的結構(一直到堆尾即可) HeapifyDown

例子:90 從二叉堆中刪除

 堆的實現(xiàn)代碼模版

Java 版本

  1. // Java 
  2.  
  3. import java.util.Arrays; 
  4. import java.util.NoSuchElementException; 
  5.  
  6.  
  7. public class BinaryHeap { 
  8.  
  9.  
  10.     private static final int d = 2; 
  11.     private int[] heap; 
  12.     private int heapSize; 
  13.  
  14.  
  15.     /** 
  16.      * This will initialize our heap with default size
  17.      */ 
  18.     public BinaryHeap(int capacity) { 
  19.         heapSize = 0; 
  20.         heap = new int[capacity + 1]; 
  21.         Arrays.fill(heap, -1); 
  22.     } 
  23.  
  24.  
  25.     public boolean isEmpty() { 
  26.         return heapSize == 0; 
  27.     } 
  28.  
  29.  
  30.     public boolean isFull() { 
  31.         return heapSize == heap.length; 
  32.     } 
  33.  
  34.  
  35.  
  36.  
  37.     private int parent(int i) { 
  38.         return (i - 1) / d; 
  39.     } 
  40.  
  41.  
  42.     private int kthChild(int i, int k) { 
  43.         return d * i + k; 
  44.     } 
  45.  
  46.  
  47.     /** 
  48.      * Inserts new element in to heap 
  49.      * Complexity: O(log N) 
  50.      * As worst case scenario, we need to traverse till the root 
  51.      */ 
  52.     public void insert(int x) { 
  53.         if (isFull()) { 
  54.             throw new NoSuchElementException("Heap is full, No space to insert new element"); 
  55.         } 
  56.         heap[heapSize] = x; 
  57.         heapSize ++; 
  58.         heapifyUp(heapSize - 1); 
  59.     } 
  60.  
  61.  
  62.     /** 
  63.      * Deletes element at index x 
  64.      * Complexity: O(log N) 
  65.      */ 
  66.     public int delete(int x) { 
  67.         if (isEmpty()) { 
  68.             throw new NoSuchElementException("Heap is empty, No element to delete"); 
  69.         } 
  70.         int maxElement = heap[x]; 
  71.         heap[x] = heap[heapSize - 1]; 
  72.         heapSize--; 
  73.         heapifyDown(x); 
  74.         return maxElement; 
  75.     } 
  76.  
  77.  
  78.     /** 
  79.      * Maintains the heap property while inserting an element. 
  80.      */ 
  81.     private void heapifyUp(int i) { 
  82.         int insertValue = heap[i]; 
  83.         while (i > 0 && insertValue > heap[parent(i)]) { 
  84.             heap[i] = heap[parent(i)]; 
  85.             i = parent(i); 
  86.         } 
  87.         heap[i] = insertValue; 
  88.     } 
  89.  
  90.  
  91.     /** 
  92.      * Maintains the heap property while deleting an element. 
  93.      */ 
  94.     private void heapifyDown(int i) { 
  95.         int child; 
  96.         int temp = heap[i]; 
  97.         while (kthChild(i, 1) < heapSize) { 
  98.             child = maxChild(i); 
  99.             if (temp >= heap[child]) { 
  100.                 break; 
  101.             } 
  102.             heap[i] = heap[child]; 
  103.             i = child; 
  104.         } 
  105.         heap[i] = temp
  106.     } 
  107.  
  108.  
  109.     private int maxChild(int i) { 
  110.         int leftChild = kthChild(i, 1); 
  111.         int rightChild = kthChild(i, 2); 
  112.         return heap[leftChild] > heap[rightChild] ? leftChild : rightChild; 
  113.     } 
  114.  
  115.  
  116.     /** 
  117.      * Prints all elements of the heap 
  118.      */ 
  119.     public void printHeap() { 
  120.         System.out.print("nHeap = "); 
  121.         for (int i = 0; i < heapSize; i++) 
  122.             System.out.print(heap[i] + " "); 
  123.         System.out.println(); 
  124.     } 
  125.  
  126.  
  127.     /** 
  128.      * This method returns the max element of the heap. 
  129.      * complexity: O(1) 
  130.      */ 
  131.     public int findMax() { 
  132.         if (isEmpty()) 
  133.             throw new NoSuchElementException("Heap is empty."); 
  134.         return heap[0]; 
  135.     } 
  136.  
  137.  
  138.     public static void main(String[] args) { 
  139.         BinaryHeap maxHeap = new BinaryHeap(10); 
  140.         maxHeap.insert(10); 
  141.         maxHeap.insert(4); 
  142.         maxHeap.insert(9); 
  143.         maxHeap.insert(1); 
  144.         maxHeap.insert(7); 
  145.         maxHeap.insert(5); 
  146.         maxHeap.insert(3); 
  147.  
  148.  
  149.         maxHeap.printHeap(); 
  150.         maxHeap.delete(5); 
  151.         maxHeap.printHeap(); 
  152.         maxHeap.delete(2); 
  153.         maxHeap.printHeap(); 
  154.     } 

 C/C++ 版本 

  1. C/C++ 
  2. #include <iostream> 
  3. using namespace std; 
  4.  
  5. class BinaryHeap { 
  6. public
  7.     BinaryHeap(int capacity); 
  8.     void insert(int x); 
  9.     int erase(int x); 
  10.     int findMax(); 
  11.     void printHeap(); 
  12.  
  13.     bool isEmpty() { return heapSize == 0; } 
  14.     bool isFull() { return heapSize == capacity; } 
  15.     ~BinaryHeap() { delete[] heap; } 
  16.  
  17. private: 
  18.     void heapifyUp(int i); 
  19.     void heapifyDown(int i); 
  20.     int maxChild(int i); 
  21.  
  22.     int parent(int i) { return (i - 1) / 2; } 
  23.     int kthChild(int i, int k) { return 2 * i + k; } 
  24.  
  25. private: 
  26.     int *heap; 
  27.     int heapSize; 
  28.     int capacity; 
  29. }; 
  30.  
  31. /** 
  32.  * This will initialize our heap with default size
  33. */ 
  34. BinaryHeap::BinaryHeap(int capacity) { 
  35.     this->heapSize = 0; 
  36.     this->capacity = capacity; 
  37.     this->heap = new int[capacity + 5]; 
  38.  
  39. /** 
  40.  * Inserts new element in to heap 
  41.  * Complexity: O(log N) 
  42.  * As worst case scenario, we need to traverse till the root 
  43.  */ 
  44. void BinaryHeap::insert(int x) { 
  45.     try { 
  46.         if (isFull())  
  47.             throw -1; 
  48.          
  49.         heap[heapSize] = x; 
  50.         heapSize ++; 
  51.         heapifyUp(heapSize - 1); 
  52.         return ; 
  53.     } catch (int e) { 
  54.         cout << "Heap is full, No space to insert new element" << endl; 
  55.         exit(-1); 
  56.     } 
  57.  
  58. /** 
  59.  * Deletes element at index x 
  60.  * Complexity: O(log N) 
  61.  */ 
  62. int BinaryHeap::erase(int x) { 
  63.     try { 
  64.         if (isEmpty())  
  65.             throw -1; 
  66.  
  67.         int maxElement = heap[x]; 
  68.         heap[x] = heap[heapSize - 1]; 
  69.         heapSize--; 
  70.         heapifyDown(x); 
  71.         return maxElement; 
  72.     } catch (int e) { 
  73.         cout << "Heap is empty, No element to delete" << endl; 
  74.         exit(-1); 
  75.     } 
  76.  
  77. /** 
  78.  * Maintains the heap property while inserting an element. 
  79.  */ 
  80. void BinaryHeap::heapifyUp(int i) { 
  81.     int insertValue = heap[i]; 
  82.     while (i > 0 && insertValue > heap[parent(i)]) { 
  83.         heap[i] = heap[parent(i)]; 
  84.         i = parent(i); 
  85.     } 
  86.     heap[i] = insertValue; 
  87.  
  88. /** 
  89.  * Maintains the heap property while deleting an element. 
  90.  */ 
  91. void BinaryHeap::heapifyDown(int i) { 
  92.     int child; 
  93.     int temp = heap[i]; 
  94.     while (kthChild(i, 1) < heapSize) { 
  95.         child = maxChild(i); 
  96.         if (temp >= heap[child]) { 
  97.             break; 
  98.         } 
  99.         heap[i] = heap[child]; 
  100.         i = child; 
  101.     } 
  102.     heap[i] = temp
  103.  
  104. int BinaryHeap::maxChild(int i) { 
  105.     int leftChild = kthChild(i, 1); 
  106.     int rightChild = kthChild(i, 2); 
  107.     return heap[leftChild] > heap[rightChild] ? leftChild : rightChild; 
  108.  
  109. /** 
  110.  * This method returns the max element of the heap. 
  111.  * complexity: O(1) 
  112.  */ 
  113. int BinaryHeap::findMax() { 
  114.     try { 
  115.         if (isEmpty())  
  116.             throw -1; 
  117.  
  118.         return heap[0]; 
  119.     } catch (int e) { 
  120.         cout << "Heap is empty." << endl; 
  121.         exit(-1); 
  122.     } 
  123.  
  124. /** 
  125.  * Prints all elements of the heap 
  126.  */ 
  127. void BinaryHeap::printHeap() { 
  128.     cout << "nHeap = "
  129.     for (int i = 0; i < heapSize; i++) 
  130.         cout << heap[i] << " "
  131.     cout << endl; 
  132.     return ; 
  133.  
  134.  
  135. int main() { 
  136.     BinaryHeap maxHeap(10); 
  137.  
  138.     maxHeap.insert(10); 
  139.     maxHeap.insert(4); 
  140.     maxHeap.insert(9); 
  141.     maxHeap.insert(1); 
  142.     maxHeap.insert(7); 
  143.     maxHeap.insert(5); 
  144.     maxHeap.insert(3); 
  145.  
  146.     maxHeap.printHeap(); 
  147.     maxHeap.erase(5); 
  148.     maxHeap.printHeap(); 
  149.     maxHeap.erase(2); 
  150.     maxHeap.printHeap(); 
  151.  
  152.     return 0; 

 Javascript 版本 

  1. // JavaScript 
  2. class BinaryHeap { 
  3.   constructor(compare) { 
  4.     this.data = []; 
  5.     this.compare = compare; 
  6.   } 
  7.  
  8.   insert(value) { 
  9.     this.insertAt(this.data.length, value); 
  10.   } 
  11.  
  12.   insertAt(index, value) { 
  13.     this.data[index] = value; 
  14.     // 對比當前節(jié)點與其父節(jié)點,如果當前節(jié)點更小就交換它們 
  15.     while (index > 0 && this.compare(value, this.data[Math.floor((index - 1) / 2)]) < 0) { 
  16.       this.data[index] = this.data[Math.floor((index - 1) / 2)]; 
  17.       this.data[Math.floor((index - 1) / 2)] = value; 
  18.       index = Math.floor((index - 1) / 2); 
  19.     } 
  20.   } 
  21.  
  22.   delete(index) { 
  23.     if (this.data.length === 0) return
  24.  
  25.     let value = this.data[index]; 
  26.     let i = index
  27.     // fix heap 
  28.     while (i < this.data.length) { 
  29.       let left = i * 2 + 1; 
  30.       let right = i * 2 + 2; 
  31.       // 沒有左子節(jié)點 
  32.       if (left >= this.data.length) break; 
  33.       // 沒有右子節(jié)點 
  34.       if (right >= this.data.length) { 
  35.         this.data[i] = this.data[left]; 
  36.         i = left
  37.         break; 
  38.       } 
  39.       // 比較左右子節(jié)點的大小,更小的補到父節(jié)點 
  40.       if (this.compare(this.data[left], this.data[right]) < 0) { 
  41.         this.data[i] = this.data[left]; 
  42.         i = left
  43.       } else { 
  44.         this.data[i] = this.data[right]; 
  45.         i = right
  46.       } 
  47.     } 
  48.     // 查看最后的空位是不是最后的葉子節(jié)點 
  49.     if (i < this.data.length - 1) { 
  50.       this.insertAt(i, this.data.pop()); 
  51.     } else { 
  52.       this.data.pop(); 
  53.     } 
  54.     return value; 
  55.   } 
  56.  
  57.   printHeap() { 
  58.     console.log("nHeap = "); 
  59.     console.log(this.data); 
  60.   } 
  61.  
  62. let maxHeap = new BinaryHeap((a, b) => b - a); 
  63. maxHeap.insert(10); 
  64. maxHeap.insert(4); 
  65. maxHeap.insert(9); 
  66. maxHeap.insert(1); 
  67. maxHeap.insert(7); 
  68. maxHeap.insert(5); 
  69. maxHeap.insert(3); 
  70.  
  71. maxHeap.printHeap(); 
  72. maxHeap.delete(5); 
  73. maxHeap.printHeap(); 
  74. maxHeap.delete(2); 
  75. maxHeap.printHeap(); 

 Python 版本 

  1. Python 
  2. import sys  
  3. class BinaryHeap:  
  4.    
  5.     def __init__(self, capacity):  
  6.         self.capacity = capacity  
  7.         self.size = 0 
  8.         self.Heap = [0]*(self.capacity + 1)  
  9.         self.Heap[0] = -1 * sys.maxsize  
  10.         self.FRONT = 1 
  11.    
  12.     def parent(self, pos):  
  13.         return pos//2 
  14.    
  15.     def leftChild(self, pos):  
  16.         return 2 * pos  
  17.    
  18.     def rightChild(self, pos):  
  19.         return (2 * pos) + 1 
  20.    
  21.     def isLeaf(self, pos):  
  22.         if pos >= (self.size//2) and pos <= self.size:  
  23.             return True 
  24.         return False 
  25.    
  26.     def swap(self, fpos, spos):  
  27.         self.Heap[fpos], self.Heap[spos] = self.Heap[spos], self.Heap[fpos]  
  28.    
  29.     def heapifyDown(self, pos):  
  30.    
  31.         if not self.isLeaf(pos):  
  32.             if (self.Heap[pos] > self.Heap[self.leftChild(pos)] or  
  33.                self.Heap[pos] > self.Heap[self.rightChild(pos)]):  
  34.    
  35.                 if self.Heap[self.leftChild(pos)] < self.Heap[self.rightChild(pos)]:  
  36.                     self.swap(pos, self.leftChild(pos))  
  37.                     self.heapifyDown(self.leftChild(pos))  
  38.    
  39.                 else:  
  40.                     self.swap(pos, self.rightChild(pos))  
  41.                     self.heapifyDown(self.rightChild(pos))  
  42.    
  43.     def insert(self, element):  
  44.         if self.size >= self.capacity :  
  45.             return 
  46.         self.size+= 1 
  47.         self.Heap[self.size] = element  
  48.    
  49.         current = self.size  
  50.    
  51.         while self.Heap[current] < self.Heap[self.parent(current)]:  
  52.             self.swap(current, self.parent(current))  
  53.             current = self.parent(current)  
  54.    
  55.     def Print(self):  
  56.         for i in range(1, (self.size//2)+1):  
  57.             print(" PARENT : "+ str(self.Heap[i])+" LEFT CHILD : "+  
  58.                                 str(self.Heap[2 * i])+" RIGHT CHILD : "
  59.                                 str(self.Heap[2 * i + 1]))  
  60.     
  61.     def minHeap(self):  
  62.    
  63.         for pos in range(self.size//2, 0, -1):  
  64.             self.heapifyDown(pos)  
  65.    
  66.     def delete(self):  
  67.    
  68.         popped = self.Heap[self.FRONT]  
  69.         self.Heap[self.FRONT] = self.Heap[self.size]  
  70.         self.size-= 1 
  71.         self.heapifyDown(self.FRONT)  
  72.         return popped  
  73.     def isEmpty(self): 
  74.         return self.size == 0 
  75.          
  76.     def isFull(self):  
  77.         return self.size == self.capacity 
  78. if __name__ == "__main__":  
  79.        
  80.     print('The minHeap is ')  
  81.     minHeap = BinaryHeap(5) 
  82.     minHeap.insert(5)  
  83.     minHeap.insert(3)  
  84.     minHeap.insert(17)  
  85.     minHeap.insert(10)  
  86.     minHeap.insert(84)  
  87.     minHeap.insert(19)  
  88.     minHeap.insert(6)  
  89.     minHeap.insert(22)  
  90.     minHeap.insert(9)  
  91.     minHeap.minHeap()  
  92.    
  93.     minHeap.Print()  
  94.     print("The Min val is " + str(minHeap.delete()))  

 高頻題目

  • 劍指 Offer 40. 最小的k個數(shù)
  • 239. 滑動窗口最大值
  • 劍指 Offer 49. 丑數(shù)
  • 347. 前 K 個高頻元素
  • HeapSort : https://www.geeksforgeeks.org/heap-sort/

總結

如果只是說堆什么?那么它是一個抽象的數(shù)據(jù)結構,表示可以非常迅速地拿到一堆數(shù)里面的最大值或者最小值,它并不少二叉堆,那么二叉堆和其他的各種堆,維基百科里面有詳細說明:https://en.wikipedia.org/wiki/Heap_(data_structure)

注意:二叉堆只是堆的一種實現(xiàn)形式,二叉堆為什么出現(xiàn)得多?是因為它較為常見且簡單,但是它并不是最優(yōu)的實現(xiàn),正是因為這個原因,所以二叉堆很多時候并不是完全的那么實用,那么如果在工程的代碼里面我們可以直接調 優(yōu)先隊列(priority_queue) 就行了。

 

責任編輯:姜華 來源: 今日頭條
相關推薦

2021-03-02 10:57:39

二叉樹二叉堆節(jié)點

2023-04-06 07:39:48

2020-08-31 07:43:58

二叉堆大頂堆存儲

2021-05-06 05:29:32

二叉堆數(shù)據(jù)結構算法

2013-05-17 15:38:22

iOS開發(fā)iOS堆棧heap stack

2020-12-11 09:49:29

二叉樹搜索樹數(shù)據(jù)

2021-10-12 09:25:11

二叉樹樹形結構

2021-09-02 11:31:28

二叉搜索樹迭代法公共祖先

2021-05-09 20:22:41

順序查找二叉查找數(shù)據(jù)結構

2020-05-09 13:49:00

內存空間垃圾

2022-04-18 07:01:36

二叉堆大根堆小根堆

2021-08-26 11:31:11

二叉樹數(shù)據(jù)結構算法

2021-01-13 09:23:23

優(yōu)先隊列React二叉堆

2023-07-31 07:48:43

Java內存虛擬機

2011-07-22 16:50:05

JAVA

2022-09-05 08:06:49

數(shù)據(jù)結構Java

2021-12-03 09:16:03

二叉樹打印平衡

2020-07-13 09:16:04

Java集合

2011-06-09 11:36:00

java

2021-01-13 10:03:36

二叉樹層序遍歷層次遍歷
點贊
收藏

51CTO技術棧公眾號