Estrutura de dados e algoritmo de classificação rápida

A classificação rápida é um algoritmo de classificação baseado no método dividir e conquistar. Ele funciona dividindo continuamente o array em submatrizes menores e classificando cada submatriz recursivamente, eventualmente classificando o array inteiro.

递归
递归
确定枢轴元素
将小于枢轴的元素放在枢轴的左边
将大于枢轴的元素放在枢轴的右边
对左子数组进行快速排序
对右子数组进行快速排序

O princípio do algoritmo de classificação rápida é o seguinte:

  1. Selecione um elemento da matriz a ser classificado como elemento pivô.
  2. Move todos os elementos menores que o elemento pivô para a esquerda do elemento pivô e move todos os elementos maiores que o elemento pivô para a direita do elemento pivô.
  3. O algoritmo de classificação rápida é chamado recursivamente na submatriz esquerda e na submatriz direita até que a submatriz tenha apenas um elemento restante ou esteja vazia.
  4. Após o término da recursão, todo o array é classificado.

Ao selecionar continuamente os elementos pivôs e dividir a matriz, o algoritmo quicksort divide a matriz em submatrizes cada vez menores até que toda a matriz seja finalmente classificada. A complexidade de tempo deste algoritmo é O(nlogn).

O método do ponteiro duplo geralmente é usado para encontrar a posição correta do elemento base. Primeiro, aponte o ponteiro esquerdo para o início do array e o ponteiro direito para o final do array. Então, o ponteiro esquerdo se move da esquerda para a direita até encontrar um elemento maior que o elemento base e parar. O ponteiro direito se move da direita para a esquerda até encontrar um elemento menor que o elemento base e parar. A seguir, troque os elementos apontados pelos ponteiros esquerdo e direito. Repita as etapas acima até que os ponteiros esquerdo e direito se encontrem. Por fim, troque o elemento base pelo elemento apontado pelo ponteiro esquerdo para que o elemento base fique na posição correta

A implementação específica é a seguinte:

// 定义一个交换函数,用于交换数组中的两个元素
function swap(arr, i, j) {
    
    
  [arr[i], arr[j]] = [arr[j], arr[i]];
}

// 定义一个分区函数,用于对数组进行分区操作
function partition(arr, left, right) {
    
    
  const pivot = arr[right - 1]; // 将分区点设置为最右边的元素
  let i = left,
    j = right - 1; // 初始化指针i和j
  while (i !== j) {
    
    
    // 当i和j指针不相遇时,进行循环
    arr[i] <= pivot ? i++ : swap(arr, i, --j); // 如果arr[i]小于等于分区点,则i指针向右移动;否则进行交换,并将j指针向左移动
  }
  swap(arr, j, right - 1); // 将分区点放置在正确的位置
  return j; // 返回分区点的索引
}

// 定义一个快速排序函数
function qsort(arr, left = 0, right = arr.length) {
    
    
  if (right - left <= 1) return; // 当要排序的元素个数小于等于1时,直接返回
  const p = partition(arr, left, right); // 进行分区操作,并获取分区点的索引p
  qsort(arr, left, p); // 对分区点左侧的子数组进行快速排序
  qsort(arr, p + 1, right); // 对分区点右侧的子数组进行快速排序
}

const arr = [5, 3, 8, 4, 2, 1, 10, 11, -4, 55];
qsort(arr); // [ -4, 1, 2, 3, 4, 5, 8, 10, 11, 55 ]
console.log(arr);

Outros métodos de implementação:

/** 
1. 第一段程序使用的是递归的方式实现快速排序。它选择数组中间的元素作为基准元素,然后将数组分割为左右两个子数组,将比基准元素小的元素放在左子数组,将比基准元素大的元素放在右子数组,然后递归地对左右两个子数组进行快速排序,最后将左右两个子数组和基准元素拼接起来作为排序结果。

2. 第二段程序使用的是基于指针的方式实现快速排序。它通过定义一个分区函数来选择基准元素,并将数组分割为左右两个子数组,然后再递归地对左右两个子数组进行快速排序。分区函数中使用了双指针的方法,从左到右找到第一个大于基准元素的元素,从右到左找到第一个小于基准元素的元素,然后交换它们的位置。这样,最终基准元素的位置就确定下来了,并且左边的元素都小于等于基准元素,右边的元素都大于基准元素。

总的来说,这两段程序的思路是相同的,都是通过不断地将数组分割为更小的子数组并排序,最后再将子数组合并成排序后的结果。它们的实现细节略有不同,但最终的结果是相同的。
*/

//---------------------------------1------------------------------------
function quickSort(arr) {
    
    
  // 如果数组长度小于等于1,则直接返回
  if (arr.length <= 1) {
    
    
    return arr;
  }

  // 选择一个基准元素
  const pivot = arr[Math.floor(arr.length / 2)];

  // 定义左右两个子数组
  const left = [];
  const right = [];

  // 将元素分割到左右两个子数组
  for (let i = 0; i < arr.length; i++) {
    
    
    if (i === Math.floor(arr.length / 2)) {
    
    
      continue; // 跳过基准元素
    }
    if (arr[i] <= pivot) {
    
    
      left.push(arr[i]);
    } else {
    
    
      right.push(arr[i]);
    }
  }

  // 递归地对左右两个子数组进行快速排序
  return quickSort(left).concat([pivot], quickSort(right));
}

// 测试
const arr = [5, 3, 8, 4, 2, 1, 10];
const sortedArr = quickSort(arr);
console.log(sortedArr); // 输出 [1, 2, 3, 4, 5, 8, 10]


//---------------------------------2------------------------------------
// 快速排序函数
function quickSort1(arr, left, right) {
    
    
  // 递归结束条件
  if (left >= right) {
    
    
    return;
  }

  // 设置左右指针及基准值
  let pivot = arr[left];
  let i = left;
  let j = right;

  // 开始一轮排序
  while (i < j) {
    
    
    // 从右侧找到比基准值小的元素
    while (i < j && arr[j] >= pivot) {
    
    
      j--;
    }

    // 将该元素放到左侧
    arr[i] = arr[j];

    // 从左侧找到比基准值大的元素
    while (i < j && arr[i] <= pivot) {
    
    
      i++;
    }

    // 将该元素放到右侧
    arr[j] = arr[i];
  }

  // 将基准值放回数组
  arr[i] = pivot;

  // 递归调用快速排序函数对左右两个子数组进行排序
  quickSort1(arr, left, i - 1);
  quickSort1(arr, i + 1, right);
}

// 测试
let arr2 = [5, 8, 2, 6, 3, 9, 1, 7, 4];
quickSort1(arr2, 0, arr2.length - 1);
console.log(arr2);

Acho que você gosta

Origin blog.csdn.net/jieyucx/article/details/133136490
Recomendado
Clasificación