[データ構造とアルゴリズム] - クイックソート

データ構造とアルゴリズム



ここに画像の説明を挿入


クイックソート

このコードはクイックソート アルゴリズムを実装します。クイックソートは、大きな問題を 2 つの小さな問題に分割し、これらの小さな問題を再帰的に解決する分割統治アルゴリズムです。具体的には、この実装では、配列の中央にある要素をピボット (ピボット) として選択し、配列を 3 つの部分 (ピボットより小さい要素、ピボットに等しい要素、ピボットより大きい要素) に分割します。次に、左部分と右部分でクイックソートを再帰的に実行し、最後にそれらをピボットとマージします。この実装の時間計算量は O(nlogn) です。ここで、n は配列の長さです。

クイックソートについて詳しく知りたい場合は、次のコード ブロックを参照してください。

Python のバージョン コード:

def quick_sort(arr): # 定义一个快速排序函数,参数为一个列表
    if len(arr) <= 1: # 如果列表长度小于等于1,直接返回该列表
        return arr
    pivot = arr[len(arr) // 2] # 取中间位置的元素作为基准值
    left = [x for x in arr if x < pivot] # 将小于基准值的元素放入左边列表
    middle = [x for x in arr if x == pivot] # 将等于基准值的元素放入中间列表
    right = [x for x in arr if x > pivot] # 将大于基准值的元素放入右边列表
    return quick_sort(left) + middle + quick_sort(right) # 递归调用快速排序函数,将左、中、右三个列表合并起来

print(quick_sort([3, 6, 1, 8, 2, 9, 4, 7, 5, 0])) # 调用快速排序函数,输出排序后的列表

ここに画像の説明を挿入

# 这一行定义了一个名为quick_sort的函数,它接受一个参数arr。
def quick_sort(arr):
	# 这一行检查输入数组arr的长度是否小于或等于1。如果是,则函数简单地返回输入数组。
    if len(arr) <= 1:
        return arr
    # 如果输入数组有多个元素,则函数将第一个元素设置为枢轴,并初始化两个名为left和right的空数组。
    else:
        pivot = arr[0]
        left = []
        right = []
        # 这个循环从第二个元素开始迭代输入数组,并将每个元素附加到left或right数组中,具体取决于它是小于还是大于枢轴。
        for i in range(1, len(arr)):
            if arr[i] < pivot:
                left.append(arr[i])
            else:
                right.append(arr[i])
         # 最后,函数在left和right数组上递归调用自身,并将排序后的left数组、枢轴和排序后的right数组连接起来返回最终排序后的数组。
        return quick_sort(left) + [pivot] + quick_sort(right)

# 这些行创建一个名为arr的数组,打印它,调用quick_sort函数对其进行排序以获得排序后的数组,然后打印排序后的数组。
arr = [3, 7, 1, 9, 2, 5, 8, 4, 6]
print("Original array:", arr)
sorted_arr = quick_sort(arr)
print("Sorted array:", sorted_arr)

def partition(li,left,right):
    temp = li[left]
    while left < right:
        while left < right and li[right] >= temp: #从右边找比temp小的数
            right -= 1
        li[left] = li[right]   #把右边的值写到左边的空位上
        print(li)
        while left < right and li[left] <= temp: #从右边找比temp小的数
            left += 1
        li[right] = li[left]   #把右边的值写到左边的空位上
        print(li)
        
    li[left] = temp
    return left

def quick_sort(li,left,right):
    if left < right: # 至少两个元素
        mid = partition(li,left,right)
        quick_sort(li,left,mid-1)
        quick_sort(li,mid+1,right)

li = [5,7,4,6,3,1,2,9,8]
print(li)
quick_sort(li,0,len(li)-1)
print(li)

ここに画像の説明を挿入

このコードは、クイックソート、パーティションという 3 つの関数を定義します。クイックソート関数は、配列 arr、左下限、右上限を入力として受け取ります。まず、左が右よりも小さいかどうかを確認し、小さい場合は、partition 関数を呼び出して配列を分割し、次に、quicksort 関数を再帰的に呼び出して、結果として得られる 2 つの部分配列を並べ替えます。

パーティション関数は、クイックソート関数と同じ入力を受け取り、パーティション化後にピボット要素のインデックスを返します。まず配列の最後の要素としてピボット要素を選択し、次に配列を左から右 1 まで反復処理します。ピボットより小さい各要素について、現在のインデックス i の要素と交換し、i を 1 ずつ増分します。最後に、ピボット要素をインデックス i+1 の要素と交換し、i+1 を返します。

# 定义快速排序函数
def quicksort(arr, left, right):
    # 如果left < right,说明还需要继续排序
    if (left < right):
        # 找到枢轴点
        pivot = partition(arr, left, right)
        # 对枢轴点左边的子序列进行排序
        quicksort(arr, left, pivot - 1)
        # 对枢轴点右边的子序列进行排序
        quicksort(arr, pivot + 1, right)

# 定义划分函数
def partition(arr, left, right):
    # 选取最后一个元素作为枢轴点
    pivot = arr[right]
    # 定义i指针,指向小于枢轴点的元素
    i = left - 1
    # 遍历整个序列
    for j in range(left, right):
        # 如果当前元素小于枢轴点
        if (arr[j] < pivot):
            # i指针右移
            i += 1
            # 交换i指针和j指针所指向的元素
            arr[i], arr[j] = arr[j], arr[i]
    # 将枢轴点放到正确的位置上
    arr[i + 1], arr[right] = arr[right], arr[i + 1]
    # 返回枢轴点的位置
    return i + 1


# 测试代码
arr = [3, 2, 1, 5, 4,7,6]
quicksort(arr, 0, len(arr) - 1)
print(arr)

ここに画像の説明を挿入

C言語のバージョンコード:

#include <stdio.h>
void quick_sort(int[], int, int);

int main()
{
    
    
    int a[50], n, i;
    printf("Enter the number of elements:"); // 打印提示信息,要求用户输入元素个数
    scanf("%d", &n); // 读取用户输入的元素个数
    printf("\nEnter the elements to be sorted:\n"); // 打印提示信息,要求用户输入待排序的元素
    for(i=0; i<n; i++)
        scanf("%d", &a[i]); // 读取用户输入的待排序元素
    quick_sort(a, 0, n-1); // 调用快速排序算法对元素进行排序
    printf("\nAfter applying quick sort, the sorted elements are: \n"); // 打印提示信息,输出排序后的元素
    for(i=0; i<n; i++)
        printf("%d ", a[i]); // 输出排序后的元素
    printf("\n");
    return 0;
}

void quick_sort(int a[], int left, int right)
{
    
    
    int j, i, pivot, temp;
    if(left<right) // 判断是否需要排序
    {
    
    
        pivot=left; // 选取第一个元素作为枢轴
        i=left;
        j=right;
        while(i<j) // 循环直到i>=j
        {
    
    
            while(a[i]<=a[pivot]&&i<right) // 从左往右找到第一个大于枢轴的元素
                i++;
            while(a[j]>a[pivot]) // 从右往左找到第一个小于等于枢轴的元素
                j--;
            if(i<j) // 如果i<j,则交换a[i]和a[j]
            {
    
    
                temp=a[i];
                a[i]=a[j];
                a[j]=temp;
            }
        }
        temp=a[pivot]; // 将枢轴放到正确的位置上
        a[pivot]=a[j];
        a[j]=temp;
        quick_sort(a, left, j-1); // 对枢轴左边的元素进行排序
        quick_sort(a, j+1, right); // 对枢轴右边的元素进行排序
    }
}


ここに画像の説明を挿入
以下は、C 言語でクイック ソート アルゴリズムを実装するコードです。

#include <stdio.h>
// 定义快速排序函数
void quicksort(int arr[], int left, int right) {
    
    
    if (left < right) {
    
     // 如果left小于right
        int pivot = arr[right]; // 将数组的最后一个元素作为基准点
        int i = left - 1; // 定义i为low-1
        for (int j = left; j <= right - 1; j++) {
    
     // 遍历数组
            if (arr[j] < pivot) {
    
     // 如果当前元素小于基准点
                i++; // i加1
                int temp = arr[i]; // 交换i和j的位置
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        int temp = arr[i + 1]; // 交换i+1和right的位置
        arr[i + 1] = arr[right];
        arr[right] = temp;
        int pi = i + 1; // 定义pi为i+1
        quicksort(arr, left, pi - 1); // 对左边的子数组进行快速排序
        quicksort(arr, pi + 1, right); // 对右边的子数组进行快速排序
    }
}

int main() {
    
    
    int arr[] = {
    
    10, 7, 8, 9, 1, 5}; // 定义数组
    int n = sizeof(arr) / sizeof(arr[0]); // 计算数组的长度
    quicksort(arr, 0, n - 1); // 对数组进行快速排序
    printf("Sorted array: "); // 输出排序后的数组
    for (int i = 0; i < n; i++) {
    
     // 遍历数组
        printf("%d ", arr[i]); // 输出数组元素
    }
    return 0; // 返回0
}


ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/guanguan12319/article/details/129837046