跳過到頁腳內容
.NET幫助

C# 優先級隊列(對於開發者的運行原理)

在 C# 中進行程式設計相當靈活,而 IronPDF 是一個強大的函式庫,能夠簡化文件的處理,尤其是在創建和修改 PDF 檔案時。 這篇文章將解釋 C# 中優先佇列的概念,並展示如何使用 IronPDF 有效地利用其優化文件處理過程。 在本文中,我們將使用 C# 優先佇列與 IronPDF 配合使用。

如何使用 C# 優先佇列

  1. 創建新的 C# 專案並建立一個優先佇列物件。
  2. 根據優先級將元素入佇列。
  3. 刪除並取出優先級最高的元素。
  4. 查看優先級最高的元素。
  5. 檢查優先佇列是否為空。
  6. 執行程式碼並釋放物件。

優先佇列

一種稱為優先佇列的資料結構,用於跟蹤多個元素,每個元素都有一個分配的優先級。 優先佇列的基本特徵是允許高效檢索,因為優先級最高的元素(或視實作而定的優先級值最低的元素)始終位於前端。 在根據優先順序處理任務或項目必須按一定順序進行的情況下,優先佇列經常被使用。

儘管 C# 標準函式庫中沒有 PriorityQueue 類,您可以自行創建或使用提供此資料結構的第三方函式庫。 陣列堆具有初始容量,當填滿且嘗試將新元素入佇列時,將創建一個更大容量的新堆。 如果兩個元素具有相同的優先級,則按照它們入佇列的順序提供服務。 為了防止競態條件,您需要開發自己的代碼以處理執行緒安全。

當元素具有對應的優先級且必須根據這些優先級進行處理時,C# 中的優先佇列提供了多種優勢。

使用 C# 優先佇列的一些優勢如下

  • 優先排序:使用優先佇列,元素能夠自動按優先級順序保留。 這保證優先級較高的元素在優先級較低的元素之前處理,從而提高基於優先級的處理效率。
  • 自訂比較:優先佇列讓您可以使用自訂的 comparer 類或構建自訂比較,從而可以根據複雜的標準排序資料。 在處理具有多種特徵或自訂優先邏輯的物件時,這很有用。
  • 快速檢索:在大多數情況下,檢索優先級最高的元素(或視實作而定的優先級最低的元素)所需的時間是一致的。這對於需要快速獲取最重要元素的演算法特別有用。

在 C# 中實作一個優先佇列

讓我們使用二元堆來構建一個基本的 C# 優先佇列系統。 請記住,您可能希望利用現有的函式庫或者考慮更複雜的生產用途方法。

using System;
using System.Collections.Generic;

public class PriorityQueue<T>
{
    private List<T> elements;
    private readonly IComparer<T> comparer;

    // Constructor that sets up the priority queue with a specific comparer
    public PriorityQueue(IComparer<T> comparer)
    {
        this.elements = new List<T>();
        this.comparer = comparer;
    }

    // Property to get the number of elements in the queue
    public int Count => elements.Count;

    // Method to add an element to the priority queue
    public void Enqueue(T item)
    {
        elements.Add(item);
        int index = Count - 1;

        // Bubble up the newly added item to maintain heap property
        while (index > 0)
        {
            int parentIndex = (index - 1) / 2;
            if (comparer.Compare(elements[parentIndex], elements[index]) <= 0)
                break;
            Swap(index, parentIndex);
            index = parentIndex;
        }
    }

    // Method to remove and return the element with the highest priority
    public T Dequeue()
    {
        if (Count == 0)
            throw new InvalidOperationException("Queue is empty.");

        T front = elements[0];
        elements[0] = elements[Count - 1];
        elements.RemoveAt(Count - 1);

        // Push down the root element to maintain heap property
        int index = 0;
        while (true)
        {
            int leftChild = 2 * index + 1;
            if (leftChild >= Count)
                break;

            int rightChild = leftChild + 1;
            int minChild = (rightChild < Count && comparer.Compare(elements[rightChild], elements[leftChild]) < 0)
                ? rightChild
                : leftChild;

            if (comparer.Compare(elements[index], elements[minChild]) <= 0)
                break;

            Swap(index, minChild);
            index = minChild;
        }

        return front;
    }

    // Helper method to swap elements in the list
    private void Swap(int i, int j)
    {
        T temp = elements[i];
        elements[i] = elements[j];
        elements[j] = temp;
    }
}
using System;
using System.Collections.Generic;

public class PriorityQueue<T>
{
    private List<T> elements;
    private readonly IComparer<T> comparer;

    // Constructor that sets up the priority queue with a specific comparer
    public PriorityQueue(IComparer<T> comparer)
    {
        this.elements = new List<T>();
        this.comparer = comparer;
    }

    // Property to get the number of elements in the queue
    public int Count => elements.Count;

    // Method to add an element to the priority queue
    public void Enqueue(T item)
    {
        elements.Add(item);
        int index = Count - 1;

        // Bubble up the newly added item to maintain heap property
        while (index > 0)
        {
            int parentIndex = (index - 1) / 2;
            if (comparer.Compare(elements[parentIndex], elements[index]) <= 0)
                break;
            Swap(index, parentIndex);
            index = parentIndex;
        }
    }

    // Method to remove and return the element with the highest priority
    public T Dequeue()
    {
        if (Count == 0)
            throw new InvalidOperationException("Queue is empty.");

        T front = elements[0];
        elements[0] = elements[Count - 1];
        elements.RemoveAt(Count - 1);

        // Push down the root element to maintain heap property
        int index = 0;
        while (true)
        {
            int leftChild = 2 * index + 1;
            if (leftChild >= Count)
                break;

            int rightChild = leftChild + 1;
            int minChild = (rightChild < Count && comparer.Compare(elements[rightChild], elements[leftChild]) < 0)
                ? rightChild
                : leftChild;

            if (comparer.Compare(elements[index], elements[minChild]) <= 0)
                break;

            Swap(index, minChild);
            index = minChild;
        }

        return front;
    }

    // Helper method to swap elements in the list
    private void Swap(int i, int j)
    {
        T temp = elements[i];
        elements[i] = elements[j];
        elements[j] = temp;
    }
}
Imports System
Imports System.Collections.Generic

Public Class PriorityQueue(Of T)
	Private elements As List(Of T)
	Private ReadOnly comparer As IComparer(Of T)

	' Constructor that sets up the priority queue with a specific comparer
	Public Sub New(ByVal comparer As IComparer(Of T))
		Me.elements = New List(Of T)()
		Me.comparer = comparer
	End Sub

	' Property to get the number of elements in the queue
	Public ReadOnly Property Count() As Integer
		Get
			Return elements.Count
		End Get
	End Property

	' Method to add an element to the priority queue
	Public Sub Enqueue(ByVal item As T)
		elements.Add(item)
		Dim index As Integer = Count - 1

		' Bubble up the newly added item to maintain heap property
		Do While index > 0
			Dim parentIndex As Integer = (index - 1) \ 2
			If comparer.Compare(elements(parentIndex), elements(index)) <= 0 Then
				Exit Do
			End If
			Swap(index, parentIndex)
			index = parentIndex
		Loop
	End Sub

	' Method to remove and return the element with the highest priority
	Public Function Dequeue() As T
		If Count = 0 Then
			Throw New InvalidOperationException("Queue is empty.")
		End If

		Dim front As T = elements(0)
		elements(0) = elements(Count - 1)
		elements.RemoveAt(Count - 1)

		' Push down the root element to maintain heap property
		Dim index As Integer = 0
		Do
			Dim leftChild As Integer = 2 * index + 1
			If leftChild >= Count Then
				Exit Do
			End If

			Dim rightChild As Integer = leftChild + 1
			Dim minChild As Integer = If(rightChild < Count AndAlso comparer.Compare(elements(rightChild), elements(leftChild)) < 0, rightChild, leftChild)

			If comparer.Compare(elements(index), elements(minChild)) <= 0 Then
				Exit Do
			End If

			Swap(index, minChild)
			index = minChild
		Loop

		Return front
	End Function

	' Helper method to swap elements in the list
	Private Sub Swap(ByVal i As Integer, ByVal j As Integer)
		Dim temp As T = elements(i)
		elements(i) = elements(j)
		elements(j) = temp
	End Sub
End Class
$vbLabelText   $csharpLabel

IronPDF

通過 .NET 函式庫 IronPDF,程式設計師可以使用 C# 語言來生成、編輯和修改 PDF 文檔。 此軟體提供了一系列的工具和功能,以促成與 PDF 檔案相關的各種操作,包括但不限於從 HTML 創建 PDF、將 HTML 轉換為 PDF、合併或分割 PDF 文件,以及在現有的 PDF 上附加文字、圖片和註解。 要了解更多關於 IronPDF 的資訊,請參閱IronPDF 文檔

IronPDF 的主要功能是其 HTML 到 PDF 轉換功能,該功能保留了佈局和樣式。 它將網頁內容轉換為 PDF,非常適合報告、發票和文檔。 這包括將 HTML 檔案、URL、HTML 字串轉換為 PDF。

using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        // Initialize the PDF renderer
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        // Initialize the PDF renderer
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
Imports IronPdf

Friend Class Program
	Shared Sub Main(ByVal args() As String)
		' Initialize the PDF renderer
		Dim renderer = New ChromePdfRenderer()

		' 1. Convert HTML String to PDF
		Dim htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"
		Dim pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent)
		pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf")

		' 2. Convert HTML File to PDF
		Dim htmlFilePath = "path_to_your_html_file.html" ' Specify the path to your HTML file
		Dim pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath)
		pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf")

		' 3. Convert URL to PDF
		Dim url = "http://ironpdf.com" ' Specify the URL
		Dim pdfFromUrl = renderer.RenderUrlAsPdf(url)
		pdfFromUrl.SaveAs("URLToPDF.pdf")
	End Sub
End Class
$vbLabelText   $csharpLabel

IronPDF 的特點

  • HTML 到 PDF 轉換:IronPDF 可以將任何類型的 HTML 資料,如文件、URL 和 HTML 代碼字串,轉換為 PDF 文件。
  • PDF 生成:可以用 C# 程式語言以程式碼方式向 PDF 文檔中添加文本、圖形和其他物件。
  • PDF 操作:IronPDF 可以修改現有的 PDF 文件並將其分割為多個文件。 它可以將多個 PDF 文件合併成一個文件。
  • PDF 表單:該函式庫在需要收集和處理表單數據的情況下很有用,因為它允許用戶創建和填寫 PDF 表單。
  • 安全性功能:IronPDF 支援密碼和權限安全以及 PDF 文檔加密。

優先佇列 with IronPDF

現在我們了解了優先佇列的基本原則,來看看 IronPDF 與它如何協作以更快地處理文檔。 假設您需要生成具有不同優先級或緊急程度的 PDF 文件。

使用 IronPDF 的優先佇列優勢

  • 文件的動態創建:您可以使用一個新的優先佇列根據不同的緊急程度或優先級動態創建 PDF 文件。
  • 有效的工作流程管理:優先佇列確保優先級較高的任務在優先級較低的任務之前完成以最大化文檔生成效率。
  • 可調整的優先排序:通過改變優先值/等級和標準,您可以迅速修改優先佇列以適應不同的情況。
  • 順利的集成:使用 IronPDF 結合同一個優先佇列可以輕鬆地將基於優先級的文檔生成集成到您的應用程式中。
  • 可擴展性:隨著程式變大,新的優先佇列擴展並能處理更多與創建 PDF 相關的操作。

以下是使用 IronPDF 的優先佇列的範例代碼。

using IronPdf;
using System;
using System.Collections.Generic;

public class PdfGenerator
{
    static void Main()
    {
        // Create a priority queue for PDF tasks
        PriorityQueue<PdfTask> pdfTaskQueue = new PriorityQueue<PdfTask>(new PdfTaskComparer());

        // Enqueue PDF tasks with different priorities
        pdfTaskQueue.Enqueue(new PdfTask("High Priority Document", Priority.High));
        pdfTaskQueue.Enqueue(new PdfTask("Medium Priority Document", Priority.Medium));
        pdfTaskQueue.Enqueue(new PdfTask("Low Priority Document", Priority.Low));

        // Process PDF tasks in order of their priority
        while (pdfTaskQueue.Count > 0)
        {
            PdfTask nextTask = pdfTaskQueue.Dequeue();
            GeneratePdf(nextTask);
        }
    }

    // Generate PDF document using IronPDF
    static void GeneratePdf(PdfTask pdfTask)
    {
        // Create a new PDF document using IronPDF
        IronPdf.HtmlToPdf renderer = new IronPdf.HtmlToPdf();
        PdfDocument pdf = renderer.RenderHtmlAsPdf($"<h1>{pdfTask.Content}</h1>");

        // Save the PDF to a file
        string pdfFilePath = $"{pdfTask.Priority}_{Guid.NewGuid()}.pdf";
        pdf.SaveAs(pdfFilePath);

        // Display confirmation message
        Console.WriteLine($"PDF generated successfully. File saved at: {pdfFilePath}");
    }
}

// Class to define a PDF task
public class PdfTask
{
    public string Content { get; }
    public Priority Priority { get; }

    public PdfTask(string content, Priority priority)
    {
        Content = content;
        Priority = priority;
    }
}

// Enum to define priority levels
public enum Priority
{
    Low,
    Medium,
    High
}

// Comparer to compare PDF tasks based on their priority
public class PdfTaskComparer : IComparer<PdfTask>
{
    public int Compare(PdfTask x, PdfTask y)
    {
        // Prioritize higher priority tasks
        return y.Priority.CompareTo(x.Priority);
    }
}
using IronPdf;
using System;
using System.Collections.Generic;

public class PdfGenerator
{
    static void Main()
    {
        // Create a priority queue for PDF tasks
        PriorityQueue<PdfTask> pdfTaskQueue = new PriorityQueue<PdfTask>(new PdfTaskComparer());

        // Enqueue PDF tasks with different priorities
        pdfTaskQueue.Enqueue(new PdfTask("High Priority Document", Priority.High));
        pdfTaskQueue.Enqueue(new PdfTask("Medium Priority Document", Priority.Medium));
        pdfTaskQueue.Enqueue(new PdfTask("Low Priority Document", Priority.Low));

        // Process PDF tasks in order of their priority
        while (pdfTaskQueue.Count > 0)
        {
            PdfTask nextTask = pdfTaskQueue.Dequeue();
            GeneratePdf(nextTask);
        }
    }

    // Generate PDF document using IronPDF
    static void GeneratePdf(PdfTask pdfTask)
    {
        // Create a new PDF document using IronPDF
        IronPdf.HtmlToPdf renderer = new IronPdf.HtmlToPdf();
        PdfDocument pdf = renderer.RenderHtmlAsPdf($"<h1>{pdfTask.Content}</h1>");

        // Save the PDF to a file
        string pdfFilePath = $"{pdfTask.Priority}_{Guid.NewGuid()}.pdf";
        pdf.SaveAs(pdfFilePath);

        // Display confirmation message
        Console.WriteLine($"PDF generated successfully. File saved at: {pdfFilePath}");
    }
}

// Class to define a PDF task
public class PdfTask
{
    public string Content { get; }
    public Priority Priority { get; }

    public PdfTask(string content, Priority priority)
    {
        Content = content;
        Priority = priority;
    }
}

// Enum to define priority levels
public enum Priority
{
    Low,
    Medium,
    High
}

// Comparer to compare PDF tasks based on their priority
public class PdfTaskComparer : IComparer<PdfTask>
{
    public int Compare(PdfTask x, PdfTask y)
    {
        // Prioritize higher priority tasks
        return y.Priority.CompareTo(x.Priority);
    }
}
Imports IronPdf
Imports System
Imports System.Collections.Generic

Public Class PdfGenerator
	Shared Sub Main()
		' Create a priority queue for PDF tasks
		Dim pdfTaskQueue As New PriorityQueue(Of PdfTask)(New PdfTaskComparer())

		' Enqueue PDF tasks with different priorities
		pdfTaskQueue.Enqueue(New PdfTask("High Priority Document", Priority.High))
		pdfTaskQueue.Enqueue(New PdfTask("Medium Priority Document", Priority.Medium))
		pdfTaskQueue.Enqueue(New PdfTask("Low Priority Document", Priority.Low))

		' Process PDF tasks in order of their priority
		Do While pdfTaskQueue.Count > 0
			Dim nextTask As PdfTask = pdfTaskQueue.Dequeue()
			GeneratePdf(nextTask)
		Loop
	End Sub

	' Generate PDF document using IronPDF
	Private Shared Sub GeneratePdf(ByVal pdfTask As PdfTask)
		' Create a new PDF document using IronPDF
		Dim renderer As New IronPdf.HtmlToPdf()
		Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf($"<h1>{pdfTask.Content}</h1>")

		' Save the PDF to a file
		Dim pdfFilePath As String = $"{pdfTask.Priority}_{Guid.NewGuid()}.pdf"
		pdf.SaveAs(pdfFilePath)

		' Display confirmation message
		Console.WriteLine($"PDF generated successfully. File saved at: {pdfFilePath}")
	End Sub
End Class

' Class to define a PDF task
Public Class PdfTask
	Public ReadOnly Property Content() As String
	Public ReadOnly Property Priority() As Priority

	Public Sub New(ByVal content As String, ByVal priority As Priority)
		Me.Content = content
		Me.Priority = priority
	End Sub
End Class

' Enum to define priority levels
Public Enum Priority
	Low
	Medium
	High
End Enum

' Comparer to compare PDF tasks based on their priority
Public Class PdfTaskComparer
	Implements IComparer(Of PdfTask)

	Public Function Compare(ByVal x As PdfTask, ByVal y As PdfTask) As Integer Implements IComparer(Of PdfTask).Compare
		' Prioritize higher priority tasks
		Return y.Priority.CompareTo(x.Priority)
	End Function
End Class
$vbLabelText   $csharpLabel

在此示例中,優先佇列(pdfTaskQueue)由 PdfGenerator 類進行排隊並處理優先等級不同的 PDF 任務。 由於 PriorityQueue,優先級較高的任務會先被處理。 我們使用 Enqueue 方法將元素加入優先佇列。 我們也可以使用 Dequeue 方法刪除並檢索優先級最高的值。 我們可以使用 peek 方法在不刪除項目的情況下查看最高優先級。

C# 優先佇列(開發人員如何運作):圖 1

範例輸出文件:

C# 優先佇列(開發人員如何運作):圖 2

根據工作的內容,GeneratePdf 函數使用 IronPDF 構建 PDF 文件,然後將其儲存到文件中。要了解更多 IronPDF 代碼,請參閱IronPDF HTML 到 PDF 範例

結論

當 IronPDF 和優先佇列結合在 C# 應用程式中時,可以根據不同的優先級或緊急程度動態快速生成文件。 這種方法在需要先於其他文檔進行處理和提供的情況下尤其有效。

通過利用 IronPDF 的 HTML 到 PDF 轉換功能並結合優先佇列進行任務管理,您的應用程式可以管理一種靈活、可擴展且具有優先級的文檔創建工作。 此文章已給出結合這些概念的框架; 可以進行其他的自訂以滿足您文檔處理操作的特定要求。 無論是在設計報告工具、文檔管理系統還是創建 PDF 的其他應用程序,通過將 IronPDF 和優先佇列結合起來,可以獲得有效且具有優先級的文件處理解決方案。

IronPDF 的$799 精簡版包括一年的軟體維護、升級選項和永久許可證。 用戶在帶水印試用期內,可在真實世界情況下評估產品。 要進一步了解 IronPDF 的費用、授權和免費試用,請參閱 IronPDF 授權資訊。 如需了解更多有關 Iron Software 的資訊,請參閱 Iron Software 網站

常見問題解答

什麼是 C# 中的優先佇列及其運作方式?

C# 中的優先佇列是一種數據結構,允許按照優先級處理元素。高優先級的元素在低優先級元素之前被服務,這對需要按緊急程度排序的任務至關重要。

如何在 C# 中實現沒有內建類的優先佇列?

您可以使用二元堆在 C# 中實現優先佇列。雖然 C# 標準庫中沒有內建的優先佇列類,但您可以創建自己的實現或使用提供此功能的第三方庫。

什麼是將優先佇列與 PDF 庫集成的好處?

將優先佇列與 IronPDF 集成允許優先化的文件生成,確保高優先級的文件被優先處理。這種集成增強了文件處理任務中的工作流效率和可擴展性。

如何在 C# 中转换 HTML 到 PDF 同時保持格式?

您可以使用 IronPDF 的 HTML 到 PDF 轉換功能來將 HTML 字串、文件或 URL 轉換成 PDF 文件。IronPDF 確保在轉換過程中保持佈局和樣式。

.NET 庫的 PDF 操作功能有哪些?

IronPDF 提供一系列功能,包括 HTML 到 PDF 轉換、PDF 生成、操作、表單處理以及密碼保護和加密等安全功能。

IronPDF 如何幫助優化文件處理程序?

IronPDF 透過允許根據優先級進行動態文件生成和操作來優化文件處理,從而很好地與優先佇列集成以實現高效的工作流管理。

你能自定優先佇列的優先順序嗎?

是的,您可以通過使用自定義比較器類或構建特定的比較邏輯來自定義優先佇列中的優先順序。這允許基於多屬性的對象進行複雜條件的排序。

使用二元堆實現優先佇列有什麼好處?

在 C# 中使用二元堆來實現優先佇列可以有效地執行插入元素和檢索最高優先級元素的操作,對於維持基於優先級的任務管理的性能至關重要。

IronPDF 如何促進基於優先級的動態文件生成?

IronPDF 可以與優先佇列一起使用,以促進動態文件生成,確保按緊急程度處理任務。這允許通過優先排序任務來高效地處理文件工作流。

PDF 庫的 Lite 版本為開發者提供什麼?

IronPDF 的 Lite 版本包括一年的軟件維護和升級選項。它提供了帶水印的試用期,讓開發者能夠在實際情境中評估其功能,然後再購買完整許可證。

Curtis Chau
技術作家

Curtis Chau 擁有卡爾頓大學計算機科學學士學位,專注於前端開發,擅長於 Node.js、TypeScript、JavaScript 和 React。Curtis 熱衷於創建直觀且美觀的用戶界面,喜歡使用現代框架並打造結構良好、視覺吸引人的手冊。

除了開發之外,Curtis 對物聯網 (IoT) 有著濃厚的興趣,探索將硬體和軟體結合的創新方式。在閒暇時間,他喜愛遊戲並構建 Discord 機器人,結合科技與創意的樂趣。