zoukankan      html  css  js  c++  java
  • C++排序算法总结

    【1】插入排序:

    是一个对少量元素进行排序的有效算法。实现比较简单。时间复杂度:O(n^2),空间复杂度:O(1)。是稳定的排序方法。

    代码:

    1. //insertion sort 
    2. #include <iostream> 
    3. using namespace std; 
    4.  
    5. //insertion sort 
    6. void InsertionSort(int *a,int n) 
    7.     int temp; 
    8.     for(int i = 1;i < n;++i) 
    9.     { 
    10.         temp = *(a + i); 
    11.         int j = i - 1; 
    12.         while(j >= 0 && *(a + j) > temp) 
    13.         { 
    14.             *(a + j + 1) = *(a + j); 
    15.             --j; 
    16.         } 
    17.         *(a + j + 1) = temp; 
    18.     } 
    19.  
    20. int main() 
    21.     int n,temp; 
    22.     cout<<"please input the number of the values that need to sort:"<<endl; 
    23.     cin>>n; 
    24.     int *a = (int*)malloc(n *sizeof(int)); 
    25.     cout<<"please input each value:"<<endl; 
    26.     for(int i = 0;i < n;++i) 
    27.     { 
    28.         cin>>temp; 
    29.         *(a + i) = temp; 
    30.     } 
    31.     /*
    32.     //insertion sort
    33.     for(int i = 1;i < n;++i)
    34.     {
    35.         temp = *(a + i);
    36.         int j = i - 1;
    37.         while(j >= 0 && *(a + j) > temp)
    38.         {
    39.             *(a + j + 1) = *(a + j);
    40.             --j;
    41.         }
    42.         *(a + j + 1) = temp;
    43.     }*/ 
    44.     InsertionSort(a,n); 
    45.  
    46.     cout<<"the values after sort:"<<endl; 
    47.     for(int i = 0;i < n;++i) 
    48.         cout<<*(a + i)<<" "
     
    1. free(a); 
     

    数据测试:


    上述代码可以改进的一个地方是:在查找插入位置的时候可以采用二分查找,但是这样依然不可以把时间复杂度降低为O(nlogn),因为移动元素的复杂度没有降低。所以时间复杂度仍然是O(n^2)。

    做此改进需要添加函数InsertLoc用于二分查找需要插入的位置,以及修改函数InsertionSort的实现。具体如下:

    1. //改进:用二分查找来找到插入的位置 
    2. //在数组a[low]---a[high]查找val插入的位置 
    3. int InsertLoc(int *a,int low,int high,int val) 
    4.     if(low == high) 
    5.     { 
    6.         if(val > *(a + low))return (low + 1); 
    7.         else 
    8.             return low; 
    9.     } 
    10.     int mid = (low + high) / 2; 
    11.     if(val > *(a + mid) && val > *(a + mid + 1)) 
    12.         return InsertLoc(a,mid + 1,high,val); 
    13.     else if(val < *(a + mid) && val < *(a + mid + 1)) 
    14.         return InsertLoc(a,low,mid,val); 
    15.     else 
    16.         return mid; 
    17.  
    18. void InsertionSort(int *a,int n) 
    19.     int temp,insert_location; 
    20.     for(int i = 1;i < n;++i) 
    21.     { 
    22.         temp = *(a + i); 
    23.         int j = i - 1; 
    24.         insert_location = InsertLoc(a,0,j,temp); 
    25.         cout<<"insert_location:"<<insert_location<<endl; 
    26.         while(j >= insert_location) 
    27.         { 
    28.             *(a + j + 1) = *(a + j); 
    29.             --j; 
    30.         } 
    31.         *(a + insert_location) = temp; 
    32.         for(int m = 0;m <= i;++m) 
    33.             cout<<*(a + m)<<" "
    34.         cout<<endl; 
    35.     } 

    【2】选择排序

    第一次找出A[0,...,n-1]的最小的元素,与A[0]交换,接着,找出A[1,...,n-1]的次小得元素,与A[1]互换。对A中头n-1个元素执行这一过程。时间复杂度:O(n^2),空间复杂度O(1)。是不稳定的排序方法。比如序列5 8 5 2 9,第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序是不稳定的排序算法。

    但是严蔚敏的《数据结构》书上面Page289页说,所有时间复杂度为O(n^2)的简单排序都是稳定的。不知道为什么?求指导~~

    其给出的简单排序的伪代码:

    1. void SelectSort(SqList &L) 
    2.     //对顺序表L做简单排序 
    3.     for(i = 1;i < L.length;++i)//选择第i小得记录,并交换到位 
    4.     { 
    5.         j = SelectMinKey(L,i);//在L.r[i..L.length]中选择key最小的记录 
    6.         if(i != j)//与第i个记录交换 
    7.         { 
    8.             temp = L.r[i]; 
    9.             L.r[i] = L.r[j]; 
    10.             L.r[j] = temp; 
    11.         } 
    12.     } 

    代码:

    1. //选择排序 
    2. #include <iostream> 
    3. using namespace std; 
    4.  
    5. void ChoseSort(int* a,int n) 
    6.     int temp,minVal,minIndex; 
    7.     for(int i = 0;i < n - 1;++i) 
    8.     { 
    9.         minVal = *(a + i);//记录a[i,...,n-1]之间的最小值 
    10.         minIndex = i;//记录a[i,...,n-1]之间的最小值的下标 
    11.         for(int j = i + 1;j < n;++j) 
    12.         { 
    13.             if(minVal > *(a + j)) 
    14.             { 
    15.                 minVal = *(a + j); 
    16.                 minIndex = j; 
    17.             } 
    18.         } 
    19.         //交换a[i]和a[i,...,n-1]之间的最小值最小值 
    20.         if(minIndex != i) 
    21.         { 
    22.             temp = *(a + i); 
    23.             *(a + i) = *(a + minIndex); 
    24.             *(a + minIndex) = temp; 
    25.         } 
    26.     } 
    27.  
    28. int main() 
    29.     int n,temp; 
    30.     cout<<"please input the number of the values that need to sort:"<<endl; 
    31.     cin>>n; 
    32.     int *a = (int*)malloc(n *sizeof(int)); 
    33.     cout<<"please input each value:"<<endl; 
    34.     for(int i = 0;i < n;++i) 
    35.     { 
    36.         cin>>temp; 
    37.         *(a + i) = temp; 
    38.     } 
    39.     ChoseSort(a,n); 
    40.     cout<<"the values after sort:"<<endl; 
    41.     for(int i = 0;i < n;++i) 
    42.         cout<<*(a + i)<<" "
    43.     free(a); 

    【3】合并排序

    采用分治法。将n个元素分成各含n/2个元素的子序列,用合并排序法对两个子序列递归的排序(子序列长度为1时递归结束),最后合并两个已排序的子序列得到结果。时间复杂度:O(nlogn),空间复杂度:O(n)。是稳定的排序方法。

    代码:

    1. //合并排序 
    2. #include <iostream> 
    3. using namespace std; 
    4.  
    5. #define MAX_VALUE 100000//用于设置哨兵,避免检查是否每一个堆都是空的 
    6.  
    7. //合并两个子数组的函数 
    8. void Merge(int *a,int p,int q,int r) 
    9.     int num1,num2; 
    10.     num1 = q - p + 1; 
    11.     num2 = r - q; 
    12.     int *a1 = (int*)malloc((num1 + 1) *sizeof(int)); 
    13.     int *a2 = (int*)malloc((num2 + 1) *sizeof(int)); 
    14.     for(int i = 0;i < num1;++i) 
    15.         *(a1 + i) = *(a + p + i); 
    16.     *(a1 + num1) = MAX_VALUE;//设置哨兵元素 
    17.     for(int i = 0;i < num2;++i) 
    18.         *(a2 + i) = *(a + q + 1 + i); 
    19.     *(a2 + num2) = MAX_VALUE;//设置哨兵元素 
    20.      
    21.     //进行排序 
    22.     int index1 = 0; 
    23.     int index2 = 0; 
    24.     for(int i = p;i <= r;++i) 
    25.     { 
    26.         if(*(a1 + index1) < *(a2 + index2)) 
    27.         { 
    28.             *(a + i) = *(a1 + index1); 
    29.             ++index1; 
    30.         } 
    31.         else 
    32.         { 
    33.             *(a + i) = *(a2 + index2); 
    34.             ++index2; 
    35.         } 
    36.     } 
    37.     free(a1); 
     
    1. free(a2); 
     
    1. //递归合并排序算法 
    2. void MergeSort(int *a,int p,int r) 
    3.     if(p < r) 
    4.     { 
    5.         int q = (p + r) / 2; 
    6.         MergeSort(a,p,q); 
    7.         MergeSort(a,q + 1,r); 
    8.         Merge(a,p,q,r); 
    9.     } 
    10.  
    11. int main() 
    12.     int n,temp; 
    13.     cout<<"please input the number of the values that need to sort:"<<endl; 
    14.     cin>>n; 
    15.     int *a = (int*)malloc(n *sizeof(int)); 
    16.     cout<<"please input each value:"<<endl; 
    17.     for(int i = 0;i < n;++i) 
    18.     { 
    19.         cin>>temp; 
    20.         *(a + i) = temp; 
    21.     } 
    22.     MergeSort(a,0,n - 1); 
    23.     cout<<"the values after sort:"<<endl; 
    24.     for(int i = 0;i < n;++i) 
    25.         cout<<*(a + i)<<" "
    26.     free(a); 
     

    如果不使用哨兵元素,需要修改Merge函数,如下:

    1. //合并两个子数组的函数(不使用哨兵元素) 
    2. void Merge(int *a,int p,int q,int r) 
    3.     int num1,num2; 
    4.     num1 = q - p + 1; 
    5.     num2 = r - q; 
    6.     int *a1 = (int*)malloc(num1 *sizeof(int)); 
    7.     int *a2 = (int*)malloc(num2 *sizeof(int)); 
    8.     for(int i = 0;i < num1;++i) 
    9.         *(a1 + i) = *(a + p + i); 
    10.     for(int i = 0;i < num2;++i) 
    11.         *(a2 + i) = *(a + q + 1 + i); 
    12.      
    13.     //进行排序 
    14.     int index1 = 0; 
    15.     int index2 = 0; 
    16.     int index = p; 
    17.     while(index1 < num1 && index2 <num2) 
    18.     { 
    19.         if(*(a1 + index1) < *(a2 + index2)) 
    20.         { 
    21.             *(a + index) = *(a1 + index1); 
    22.             ++index; 
    23.             ++index1; 
    24.         } 
    25.         else
    26.             *(a + index) = *(a2 + index2); 
    27.             ++index; 
    28.             ++index2; 
    29.         } 
    30.     } 
    31.     while(index1 < num1) 
    32.     { 
    33.         *(a + index) = *(a1 + index1); 
    34.         ++index; 
    35.         ++index1; 
    36.     } 
    37.     while(index2 < num2) 
    38.     { 
    39.         *(a + index) = *(a2 + index2); 
    40.         ++index; 
    41.         ++index2; 
    42.     } 
    43.     free(a1);<pre class="cpp" name="code">  free(a2);</pre> 
    44. <pre></pre> 
    45. <pre class="cpp" name="code">}</pre> 
    46. <p><span style="color: rgb(255, 0, 0); font-family: KaiTi_GB2312; font-size: 24px;"><strong>【4】冒泡排序</strong></span></p> 
    47. <p>每一趟都比较相邻两个元素,若是逆序的,则交换。结束的条件应该是“在一趟排序过程中没有进行过交换元素的操作”。时间复杂度:O(n^2),空间复杂度O(1)。是稳定的排序。</p> 
    48. <pre class="cpp" name="code">#include <iostream> 
    49. using namespace std; 
    50.  
    51. void BubbleSort(int *a,int n) 
    52.     int flag,temp;//标记是否进行过交换操作 
    53.     for(int i = 0;i < n - 1;++i) 
    54.     { 
    55.         flag = 0; 
    56.         for(int j = 0;j < n - 1 - i;++j) 
    57.         { 
    58.             if(*(a + j) > *(a + j + 1)) 
    59.             { 
    60.                 temp = *(a + j); 
    61.                  *(a + j) =  *(a + j + 1); 
    62.                  *(a + j + 1) = temp; 
    63.                  flag = 1; 
    64.             } 
    65.         } 
    66.         if(flag == 0)break
    67.     } 
    68.  
    69. int main() 
    70.     int n,temp; 
    71.     cout<<"please input the number of the values that need to sort:"<<endl; 
    72.     cin>>n; 
    73.     int *a = (int*)malloc(n *sizeof(int)); 
    74.     cout<<"please input each value:"<<endl; 
    75.     for(int i = 0;i < n;++i) 
    76.     { 
    77.         cin>>temp; 
    78.         *(a + i) = temp; 
    79.     } 
    80.     BubbleSort(a,n); 
    81.     cout<<"the values after sort:"<<endl; 
    82.     for(int i = 0;i < n;++i) 
    83.         cout<<*(a + i)<<" "
    84. <pre class="cpp" name="code">   free(a);</pre> 
    85. <pre></pre> 
    86. <pre class="cpp" name="code">}</pre> 
    87. <p><span style="color: rgb(255, 0, 0); font-family: KaiTi_GB2312; font-size: 24px;"><strong>【5】快速排序</strong></span></p> 
    88. <p>它是对冒泡排序的一种改进。它的基本思想是:通过一趟排序将待排序元素分成两个部分,其中一部分元素比另一部分元素小。再分别对这两部分元素进行排序。以达到整个元素序列有序。时间复杂度:O(nlogn),空间复杂度O(logn),是不稳定的算法。</p> 
    89. <p>代码:</p> 
    90. <pre class="cpp" name="code">#include <iostream> 
    91. using namespace std; 
    92.  
    93. int Partition(int *a,int low,int high) 
    94.     int PivotKey = *(a + low);//用第一个元素做枢轴 
    95.     while(low < high) 
    96.     { 
    97.         while(low < high && *(a + high) > PivotKey)--high; 
    98.         *(a + low) = *(a + high); 
    99.         while(low < high && *(a + low) < PivotKey)++low; 
    100.         *(a + high) = *(a + low); 
    101.     } 
    102.     *(a + low) = PivotKey; 
    103.     return low; 
    104.  
    105. void QuickSort(int *a,int low,int high) 
    106.     if(low < high) 
    107.     { 
    108.         int PivotLoc = Partition(a,low,high); 
    109.         QuickSort(a,low,PivotLoc - 1); 
    110.         QuickSort(a,PivotLoc + 1,high); 
    111.     } 
    112.  
    113. int main() 
    114.     int n,temp; 
    115.     cout<<"please input the number of the values that need to sort:"<<endl; 
    116.     cin>>n; 
    117.     int *a = (int*)malloc(n *sizeof(int)); 
    118.     cout<<"please input each value:"<<endl; 
    119.     for(int i = 0;i < n;++i) 
    120.     { 
    121.         cin>>temp; 
    122.         *(a + i) = temp; 
    123.     } 
    124.     QuickSort(a,0,n - 1); 
    125.     cout<<"the values after sort:"<<endl; 
    126.     for(int i = 0;i < n;++i) 
    127.         cout<<*(a + i)<<" "
    128.     free(a);}</pre> 
    129. <p><br> 
    130. </p> 
    131. <p><span style="color: rgb(255, 0, 0); font-family: KaiTi_GB2312; font-size: 24px;"><strong>【6】计数排序</strong></span></p> 
    132. <p>计数排序的思想是对每一个输入元素x,确定出小于x的元素的个数。然后我们就可以直接把它放在嘴中输出数组中相应的位置上。</p> 
    133. <p>但是计数排序基于这样一个假设:n个输入元素的每一个大小范围都是[0,k]。</p> 
    134. <p>代码:</p> 
    135. <p><pre class="cpp" name="code">#include <iostream> 
    136. using namespace std; 
    137.  
    138. //Counting Sort Algorithm 
    139. //A:array before sorting 
    140. //B:array after sorting 
    141. //n:the number of A 
    142. //k:all the elements is in [0,k] 
    143. void CountintSort(int A[],int *B,int n,int k,int *C) 
    144.     //初始化C数组 
    145.     for (int i = 0;i <= k;++i) 
    146.     { 
    147.         C[i] = 0; 
    148.     } 
    149.  
    150.     for (int i = 0;i < n;++i) 
    151.     { 
    152.         ++C[A[i]];//C[i]:值等于i的元素的个数 
    153.     } 
    154.  
    155.     for (int i = 1;i <= k;++i) 
    156.     { 
    157.         C[i] += C[i - 1];//C[i]:值小于等于i的元素的个数 
    158.     } 
    159.      
    160.     for (int i = n - 1;i >= 0;--i) 
    161.     { 
    162.         B[C[A[i]] - 1] = A[i];//注意:下标索引从0开始! 
    163.         --C[A[i]]; 
    164.     } 
    165.  
    166. int main() 
    167.     int A[6] = {2,7,1,4,0,3}; 
    168.     int n = 6; 
    169.     int k = 7; 
    170.     int *B = (int *)malloc(n *sizeof(int)); 
    171.     int *C = (int *)malloc((k + 1) *sizeof(int)); 
    172.     cout << "排序之前的元素:" << endl; 
    173.     for (int i = 0;i < n;++i) 
    174.     { 
    175.         cout << A[i] << " "
    176.     } 
    177.     cout << endl; 
    178.     CountintSort(A,B,n,k,C); 
    179.     cout << "排序之后的元素:" << endl; 
    180.     for (int i = 0;i < n;++i) 
    181.     { 
    182.         cout << B[i] << " "
    183.     } 
    184.     cout << endl; 
    185.     free(B); 
    186.     free(C); 
    187. }</pre><br> 
    188. 运行结果:<p></p> 
    189. <p><img alt="" src="http://my.csdn.net/uploads/201206/10/1339316958_2887.jpg"><br> 
    190. </p> 
    191. <p><strong>时间复杂度分析:</strong></p> 
    192. <p>时间复杂度是O(k + n)。一般,当k = O(n)时,常常采用计数排序。这时候的运行时间为O(n)。</p> 
    193. <p>计数排序是稳定的排序。</p> 
    194. <p><br> 
    195. </p> 
    196. <p>一些好的参考资料:不同排序算法间的比较:<a href="http://commons.wikimedia.org/wiki/File:SortingAlgoComp.png">http://commons.wikimedia.org/wiki/File:SortingAlgoComp.png</a><br> 
    197. 一些排序算法的 C 及 Pascal 实现 :<br> 
    198. <a href="http://www.nocow.cn/index.php/%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95">http://www.nocow.cn/index.php/%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95</a></p> 
    199. <p>最后,简要比较一下各排序算法,转自维基百科:</p> 
    200. <p><span id=".E7.AE.80.E8.A6.81.E6.AF.94.E8.BE.83"class="mw-headline">简要比较</span> 
    201. <table class="wikitable     "
    202. <tbody> 
    203. <tr> 
    204. <th rowSpan="2">名称</th> 
    205. <th rowSpan="2">数据对象</th> 
    206. <th rowSpan="2">稳定性</th> 
    207. <th colSpan="2">时间复杂度</th> 
    208. <th rowSpan="2">空间复杂度</th> 
    209. <th rowSpan="2">描述</th> 
    210. </tr> 
    211. <tr> 
    212. <th>平均</th> 
    213. <th>最坏</th> 
    214. </tr> 
    215. <tr> 
    216. <td>插入排序</td> 
    217. <td>数组、链表</td> 
    218. <td>√</td> 
    219. <td colSpan="2"><span dir="ltr"class="texhtml"><em>O</em>(<em>n</em><sup>2</sup>)</span></td> 
    220. <td>O(1)</td> 
    221. <td>(有序区,无序区)。把无序区的第一个元素插入到有序区的合适的位置。对数组:比较得少,换得多。</td> 
    222. </tr> 
    223. <tr> 
    224. <td rowSpan="2">直接选择排序</td> 
    225. <td>数组</td> 
    226. <td>×</td> 
    227. <td rowSpan="2" colSpan="2"><span dir="ltr"class="texhtml"><em>O</em>(<em>n</em><sup>2</sup>)</span></td> 
    228. <td rowSpan="2">O(1)</td> 
    229. <td rowSpan="2">(有序区,无序区)。在无序区里找一个最小的元素跟在有序区的后面。 对数组:比较得多,换得少。</td> 
    230. </tr> 
    231. <tr> 
    232. <td>链表</td> 
    233. <td>√</td> 
    234. </tr> 
    235. <tr> 
    236. <td>堆排序</td> 
    237. <td>数组</td> 
    238. <td>×</td> 
    239. <td colSpan="2">O(nlogn)</td> 
    240. <td>O(1)</td> 
    241. <td>(最大堆,有序区)。从堆顶把根卸出来放在有序区之前,再恢复堆。</td> 
    242. </tr> 
    243. <tr> 
    244. <td>归并排序</td> 
    245. <td>数组、链表</td> 
    246. <td>√</td> 
    247. <td colSpan="2">O(nlogn)</td> 
    248. <td>O(n) +O(logn) , 如果不是从下到上</td> 
    249. <td>把数据分为两段,从两段中逐个选最小的元素移入新数据段的末尾。可从上到下或从下到上进行。</td> 
    250. </tr> 
    251. <tr> 
    252. <td>快速排序</td> 
    253. <td>数组</td> 
    254. <td>×</td> 
    255. <td>O(nlogn)</td> 
    256. <td><span dir="ltr" class="texhtml"><em>O</em>(<em>n</em><sup>2</sup>)</span></td> 
    257. <td>O(logn) ,O(n)</td> 
    258. <td>(小数,枢纽元,大数)。</td> 
    259. </tr> 
    260. <tr> 
    261. <td>Accum qsort</td> 
    262. <td>链表</td> 
    263. <td>√</td> 
    264. <td>O(nlogn)</td> 
    265. <td><span dir="ltr" class="texhtml"><em>O</em>(<em>n</em><sup>2</sup>)</span></td> 
    266. <td>O(logn) ,O(n)</td> 
    267. <td>(无序区,有序区)。把无序区分为(小数,枢纽元,大数),从后到前压入有序区。</td> 
    268. </tr> 
    269. <tr> 
    270. <td colSpan="7"> </td> 
    271. <td> </td> 
    272. </tr> 
    273. <tr> 
    274. <td>决策树排序</td> 
    275. <td> </td> 
    276. <td>√</td> 
    277. <td colSpan="2">O(logn!)</td> 
    278. <td>O(n!)</td> 
    279. <td>O(n) <O(logn!) <O(nlogn)</td> 
    280. </tr> 
    281. <tr> 
    282. <td colSpan="7"> </td> 
    283. <td> </td> 
    284. </tr> 
    285. <tr> 
    286. <td>计数排序</td> 
    287. <td>数组、链表</td> 
    288. <td>√</td> 
    289. <td colSpan="2">O(n)</td> 
    290. <td>O(n+m)</td> 
    291. <td>统计小于等于该元素值的元素的个数 i,于是该元素就放在目标数组的索引 i位。(i≥0)</td> 
    292. </tr> 
    293. <tr> 
    294. <td>桶排序</td> 
    295. <td>数组、链表</td> 
    296. <td>√</td> 
    297. <td colSpan="2">O(n)</td> 
    298. <td>O(m)</td> 
    299. <td>将值为 i 的元素放入i 号桶,最后依次把桶里的元素倒出来。</td> 
    300. </tr> 
    301. <tr> 
    302. <td>基数排序</td> 
    303. <td>数组、链表</td> 
    304. <td>√</td> 
    305. <td colSpan="2"> </td> 
    306. <td> </td> 
    307. <td>一种多关键字的排序算法,可用桶排序实现。</td> 
    308. </tr> 
    309. </tbody> 
    310. </table> 
    311. <p></p> 
    312. <ul> 
    313. <li>均按从小到大排列 </li><li>n 代表数据规模 </li><li>m 代表数据的最大值减最小值 </li></ul> 
    314. <div><pre class="cpp" name="code"></pre></div><div></div><pre></pre> 
    315. <pre></pre> 
    316. <pre></pre> 
    317. <pre></pre> 
    318. <pre></pre> 
    319. <pre></pre> 
    320. <pre></pre> 
    321. <pre></pre> 
    322. </pre> 
  • 相关阅读:
    POJ 1015 Jury Compromise【DP】
    POJ 1661 Help Jimmy【DP】
    HDU 1074 Doing Homework【状态压缩DP】
    HDU 1024 Max Sum Plus Plus【DP,最大m子段和】
    占坑补题。。最近占的坑有点多。。。
    Codeforces 659F Polycarp and Hay【BFS】
    Codeforces 659E New Reform【DFS】
    Codeforces 659D Bicycle Race【计算几何】
    廖大python实战项目第四天
    廖大python实战项目第三天
  • 原文地址:https://www.cnblogs.com/wuyida/p/6301190.html
Copyright © 2011-2022 走看看