主頁 > 後端開發 > 內事不決問張昭,外事不決問周瑜,“ 排序 ”不決問威少

內事不決問張昭,外事不決問周瑜,“ 排序 ”不決問威少

2021-10-06 08:18:37 後端開發

排序

  • 排序的穩定性
  • 一、直接插入排序
  • 二、希爾排序
  • 三、選擇排序
  • 四、冒泡排序
  • 五、堆排序
  • 六、快速排序
    • Partition
      • 挖坑法實作Partition
      • Hoare法實作Partition
    • 遞回分治
      • 時間空間復雜度
    • 優化
      • 三數取中
    • 非遞回分治
  • 七、歸并排序
    • 歸并排序(遞回)
    • 非遞回的歸并排序
  • 時間復雜度與空間復雜度
    • 計算運行時間的小妙招
  • 買七送一(基數排序)

排序的穩定性

兩個相等的資料,經過排序后,排序演算法保證其相對位置不發生變化,則稱這個排序演算法就有穩定性
在這里插入圖片描述
判斷方法:如果再比較的程序中沒有發生跳躍式的交換(即非相鄰的交換),那么就是穩定的

一、直接插入排序

在這里插入圖片描述

  1. 用 i 遍歷陣列,j = i - 1,將當前元素找到合適的位置插入,這個位置要滿足 前面元素小于它
  2. 將當前元素存在 temp 中,j 下標的元素與temp 比較,如果array[ j ]>temp,說明temp插入的位置 j 下標前面,將 j 下標的元素后移一位,j - -
  3. 再進入回圈判斷
  4. 當 j < 0 的時候,退出回圈,說明當前元素的位置是0下標
  5. 如果array[ j ] < temp , 將temp 放到 j+1 下標中,退出回圈,說明當前元素已經找到了合適的位置
  6. 此時 temp 前的區間有序了
    public static void insertSort(int[] array){
        for (int i = 1; i < array.length; i++) {
            int temp = array[i];
            int j = i-1;
            for (; j >= 0; j--) {
                if(array[j] > temp){
                //此處>=就不穩定了
                    array[j+1] = array[j];
                }else{
                    array[j+1] = temp;
                    break;
                }
            }
            if(j < 0){
                array[0] = temp;
            }
        }
    }

如果一組資料量比較小,越趨近于有序,用直接插入排序越快

二、希爾排序

  • 希爾排序是對直接插入排序的優化

  • 先分組進行預排序,即對每組進行直接插入排序,每組的資料量小,排序快

  • 不斷減少組數,進行預排序,進一步提高整體資料的有序性

  • 直到最后為一組,進行直接插入排序

  • 大大的降低了直接插入排序的時間復雜度
    在這里插入圖片描述

  • 每分一次組,就進行一次直接插入排序;資料量不同,分組的方式也不同,必須保證最后一次只有一組

  • gap越大,步子越大,移動的越快,越無序

    public static void shell(int[] array, int gap){
        for (int i = gap; i < array.length; i++) {
            int temp = array[i];
            int j = i-gap;
            for (; j >=0 ; j -= gap) {
                if(array[j] > temp){
                    array[j+gap] = array[j];
                }else{
                    array[j+gap] = temp;
                    break;
                }
            }
            if(j < 0){
                array[gap+j] = temp;
            }
        }
    }
    public static void shellSort(int[] array){
        int gap = array.length;
        while(gap > 1){
            gap = gap/3+1;
         // gap = gap/2;
            shell(array,gap);
        }
    }

三、選擇排序

在這里插入圖片描述

  • 用 i 遍歷一次整個陣列
  • j = i+1, j 向后遍歷,如果當前 j 下標的元素小于當前 i 下標的元素,交換這兩個元素,j 繼續向后遍歷;第一次遍歷完成后 i 下標的元素就是當前陣列最小的元素
  • 當 i 遍歷完成這個陣列,排序完畢
    public void selectSort(int[] array){
        for (int i = 0; i < array.length-1; i++) {
            for (int j = i+1; j < array.length; j++) {
                if(array[i] > array[j]){
                    int temp  = array[i];
                    array[i] = array[j];
                    array[j] = temp;
                }
            }
        }
    }

四、冒泡排序

在這里插入圖片描述

  • i 表示排序的次數
  • 通過 j 遍歷陣列,如果 j 下標的元素 > j + 1下標的元素,交換這兩個元素,j 繼續向后遍歷,第一趟排序后最后一個元素就是最大的元素
  • 再進行第二趟排序,注意 j 的結束下標的位置
    public static void bullerSort(int[] array){
        boolean flg = true;
        for (int i = 0; i < array.length-1; i++) {
            for (int j = 0; j < array.length-1-i; j++) {
                if(array[j] > array[j+1]){
                    int temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                    flg = false;
                }
            }
            if(flg){
                break;
            }
        }
    }

五、堆排序

  • 先將陣列變成一個大堆
  • 堆頂元素與堆尾的元素互換
  • 從堆頂元素向下調整,再次成為大堆,注意調整區間的范圍(較上一次-1)
  • 堆頂元素和倒數第二個元素互換
  • 再次向下調整
  • 照此回圈,直至堆頂元素
//向下調整
//這里的end是結束區間的下標,注意不是長度len
    public static void adjustDown(int[] array, int begin, int end){
        int parent = begin;
        int child = parent*2+1;
        while(child <= end){
            if(child+1 <= end && array[child+1] > array[child]){
                child++;
            }
            if(array[parent] < array[child]){
                int temp = array[parent];
                array[parent] = array[child];
                array[child] = temp;
            }else{
                break;
            }
            parent = child;
            child = child*2+1;
        }
    }
//建立一個大堆
    public static void creayHeap(int[] array){
        int parent = (array.length-1-1)/2;
        for (int i = parent; i >= 0; i--) {
            adjustDown(array,i,array.length-1);
        }
    }
//堆排序
    public static void heapSort(int[] array){
        creayHeap(array);
        int end = array.length-1;
        while(end > 0){
            int temp = array[0];
            array[0] = array[end];
            array[end] = temp;
            end--;
            adjustDown(array,0,end);
        }
    }

六、快速排序

  • 從待排序區間里選一個數,作為基準值(pivot)
  • Partition:遍歷整個區間,將比基準值小的放到基準值的左邊,將比基準值大的放到基準值的右邊
  • 分治思想,對左右兩個小區間按照同樣的方式處理,知道小區間的長度為1,代表已經有序;或小區間的長度為0,代表沒有資料

Partition

挖坑法實作Partition

在這里插入圖片描述

  • 取第一個元素作為基準(pivot)
  • low下標從左邊開始遍歷,high下標從右邊開始遍歷,low和high就是“坑”
  • 首先low下標作為“坑”,需要比 pivot 小的元素填坑,high–,找到比pivot 小的元素,賦值給low
  • 然后high下標作為“坑”,需要比pivot 大的元素填坑,low++,找到比pivot 大的元素,賦值給high
  • 當low和high相遇時,此下標指向的元素就是 pivot
  • 一次Patition結束,此時low/high的左邊是比pivot小的元素,low/high右邊是比pivot大的元素
  • 回傳pivot的下標(low/high),作為下一次Patition的區間
public static int Partition(int[] array, int low, int high){
        int pivot = array[low];
        while(low < high){
//注意這兩個回圈的順序,先low后high,第一個坑沒法填,最后一個數白白喪失
//注意一定是>= / <= ,而不是> <,如果< , > 相等的也交換,死回圈
            while(low < high && array[high] >= pivot){
                high--;
            }
            array[low] = array[high];
            while(low < high && array[low] <= pivot){
                low++;
            }
            array[high] = array[low];
        }
        array[low] = pivot;
        return low;
    }

Hoare法實作Partition

在這里插入圖片描述

  • 第一個元素作為基準(pivot)
  • high從右邊開始遍歷,left從左邊開始遍歷
  • high找到比 pivot 小的元素,low找到比 pivot 大的元素,交換元素
  • high與left相遇時,此下標指向的元素 小于pivot ,與 區間起點 的元素交換
  • 回傳pivot的下標(low/high),作為下一次Patition的區間
    public static void Swap(int[] array, int i, int j){
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    public static int Hoare(int[] array, int low, int high){
        int start = low;
        int pivot = array[low];
        while(low < high){
    //注意順序,先后再前,讓high去找low,兩者相遇的地方是比temp小的數
    //同樣的必須是>= <=,如果是>,< 會死回圈的
            while(low < high && array[high] >= pivot){
                high--;
            }
            while(low < high && array[low] <= pivot){
                low++;
            }
            Swap(array,low,high);
        }
        Swap(array,low,start);
        return low;
    }

遞回分治

  • 通過遞回的方式對左右兩個小區間再進行快速排序,直到區間長度為1時,遞回結束
    public static void quickSort(int[] array, int start, int end){
        if(start >= end){
            return;
        }
        int pivot = Partition(array,start,end);

        quickSort(array,start,pivot-1);
        quickSort(array,pivot+1,end);
    }
    public static void quickSort(int[] array){
        quickSort(array,0,array.length-1);
    }

時間空間復雜度

穩定性:不穩定
在這里插入圖片描述
最壞情況時,可能會出現堆疊溢位的情況
所以可以通過基準值的選擇進行優化

優化

  1. 基準值的選擇
  • 選擇邊上(low或者high)
  • 隨機選擇,可以將隨機下標的值與low下標的值互換
  • 三數取中,要求 array[mid] <= array[low] <= array[high]
  1. 待排序區間小于一個閾值時,使用直接插入排序

三數取中

還是array[low] 作基準(pivot)
三數取中
array[mid] <= array[low] <= array[high]
可以確定其中最大/最小數的位置,在比較其余兩個數

//元素交換
    public static void Swap(int[] array, int i, int j){
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
//array[mid] <= array[low] <= array[high]
    public static void ThreeMiddle(int[] array,int low, int high){
        int mid = (low+high)/2;
        if(array[low] < array[mid]){
            Swap(array,low,mid);
        }
        if(array[high] < array[low]){
            Swap(array,low,high);
        }
        if(array[low] < array[mid]){
        Swap(array,low,mid);
        }
        
        //先確定mid的位置
        if(array[mid] > array[start]){
            swap(array,start,mid);
        }
        if(array[mid] > array[end]){
            swap(array,mid,end);
        }
        //確定完成
        if(array[start] > array[end]){
            swap(array,start,end);
        }
        
        //先確定high的位置
        if(array[mid] > array[high]){
            Swap(array,mid,high);
        }
        if(array[low] > array[high]){
            Swap(array,low,high);
        }
        //確定完成
        if(array[mid] > array[low]){
            Swap(array,mid,low);
        }
    }

非遞回分治

在這里插入圖片描述

  • 呼叫Partition后,找到pivot
  • 把當前pivot的左區間和右區間的邊界下標放到堆疊中,當這個區間至少有兩個元素的時候,才入堆疊;若只有一個元素,說明有序了,不再入堆疊
  • 判斷堆疊是否為空,如果不為空的話,彈出堆疊頂的兩個元素,放的順序決定第一個元素給low還是給high
  • 再進行Partition
    public static void quickSort2(int[] array){
        if(array.length == 0){
            return;
        }
        Stack<Integer> stack = new Stack<>();
        stack.push(0);
        stack.push(array.length-1);
        while(!stack.isEmpty()){
            int high = stack.pop();
            int low = stack.pop();
            int pivot = Partition(array,low,high);
            if(pivot > low+1) {
                stack.push(low);
                stack.push(pivot - 1);
            }
            if(pivot < high-1) {
                stack.push(pivot + 1);
                stack.push(high);
            }
        }
    }

七、歸并排序

先將已有的序列分解成較短的子序列,使每個子序列有序,再將已經有序的子序列合并,得到完全有序的序列,即分解與合并

在這里插入圖片描述

歸并排序(遞回)

  • 將陣列通過遞回分解,直到low=high時(即只有一個元素的時候),遞回結束
  • 將兩個有序陣列 合并成 一個有序陣列
public static void merge(int[] array, int low, int mid, int high){
        int[] temp = new int[high-low+1];
        int k = 0;
        int s1 = low;
        int e1 = mid;
        int s2 = mid+1;
        int e2 = high;
        while(s1 <= e1 && s2 <= e2){
            while(s1 <= e1 && array[s1] <= array[s2]){
                temp[k++] = array[s1++];
            }
            while(s2 <= e2 && array[s2] <= array[s1]){
                temp[k++] = array[s2++];
            }
        }
        while(s1 <= e1){
            temp[k++] = array[s1++];
        }
        while(s2 <= e2){
            temp[k++] = array[s2++];
        }
        for (int i = 0; i < temp.length; i++) {
            array[i+low] = temp[i];
        }
    }
    public static void mergeSort(int[] array, int low, int high){
        if(low == high){
            return;
        }
        int mid = (low+high)/2;
        mergeSort(array,low,mid);
        mergeSort(array,mid+1,high);
        merge(array, low, mid, high);
    }

    public static void mergeSort(int[] array){
        mergeSort(array,0,array.length-1);
    }

非遞回的歸并排序

  • 通過gap控制需要合并的兩個序列的長度,1–>2–>4–>8…
  • 在gap的一次回圈中,s1、e1、s2、e2遍歷所有的序列,合并兩個有序的序列
  • 可能序列正好匹配 可能只剩下一段序列(沒有與之合并的第二段序列);如果剩下無法合并的序列,不做改變
public static void merge(int[] array, int gap){
        int[] temp = new int[array.length];
        int k = 0;
        int s1 = 0;
        int e1 = s1+gap-1;
        int s2 = e1+1;
        int e2 = s2+gap-1 > array.length-1 ? array.length-1 : s2+gap-1;
        //有兩段
        while(s2 < array.length) {
            while (s1 <= e1 && s2 <= e2) {
                while (s1 <= e1 && array[s1] <= array[s2]) {
                    temp[k++] = array[s1++];
                }
                while (s2 <= e2 && array[s2] <= array[s1]) {
                    temp[k++] = array[s2++];
                }
            }
            while(s1 <= e1) {
                temp[k++] = array[s1++];
            }
            while(s2 <= e2){
                temp[k++] = array[s2++];
            }
            s1 = e2+1;
            e1 = s1+gap-1;
            s2 = e1+1;
            e2 = s2+gap-1 > array.length-1 ? array.length-1 : s2+gap-1;
        }
        //只有一段了
        while(s1 < array.length && s1 <= e1){
            temp[k++] = array[s1++];
        }

        for (int i = 0; i < temp.length; i++) {
            array[i] = temp[i];
        }
    }
    public static void mergeSort2(int[] array){
        for (int gap = 1; gap < array.length; gap*=2) {
            merge(array,gap);
        }
    }

時間復雜度與空間復雜度

在這里插入圖片描述

計算運行時間的小妙招

        long begin = System.currentTimeMillis();
        insertSort(array);
        long end = System.currentTimeMillis();
        System.out.println(end - begin);

買七送一(基數排序)

基數排序又叫“桶子排序”

  • 先給10個桶子 標號0~10
  • 將所有元素按個位數放入對應的桶中
  • 依次取出完成第一次排序
  • 再將所有元素按十位數放入對應的桶中
  • 依次取出完成第二次排序
  • 注意從桶中取出元素的時候要 桶底元素先出,桶頂元素后出
    在這里插入圖片描述

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/305673.html

標籤:java

上一篇:【Java】瘋狂作圖之剖釋String類之媽見夸之作

下一篇:速學 | 如何幫女朋友用Java合并兩個PDF

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more