pilha
1. A estrutura heap é uma estrutura de árvore binária completa implementada com um array.O
subscrito do filho esquerdo do nó raiz é: 2 i+1, e o subscrito do filho direito é 2 i+2. O nó pai dos dois filhos é (i-1)/2 arredondado para 2.
Em uma árvore binária completa, se o valor máximo de cada subárvore estiver no topo, trata-se de uma grande pilha raiz.
Compare o filho com o nó nó pai de baixo para cima. Se a folha filho Se o valor do nó for maior que o nó raiz, então troque, caso contrário, pare a comparação ascendente 3,
na árvore binária completa, se o valor mínimo de cada subárvore estiver em o topo, o heap raiz pequeno é
oposto ao heap raiz grande
4, o heapInsert e o heapify da estrutura do heap operam
na raiz grande A comparação entre o heap e o heap raiz pequeno é o processo de heapInsert; a
demonstração de código do heap heap raiz grande heapInsert:
void heapify(vector<int> &a, int index)
{
while (a[index] > a[(index - 1) / 2])
{
//两个元素互换
swap(a, a[index], a[(index - 1) / 2]);
//向上反馈
index = (index - 1) / 2;
}
}
Operação Heapify:
aqui está um exemplo, quando o usuário deseja excluir o valor máximo no heap raiz grande, primeiro precisamos substituir o último número na matriz para a posição 0 na matriz e, em seguida, o nó raiz começa a comparar com o valor mínimo dos dois nós cotilédones Troque e, em seguida, compare e troque o nó raiz substituído com os dois nós cotilédones na posição atual após a troca.
void heapify(vector<int> &a, int index, int heapsize)
{
//index表示从何位置开始进行heapify操作操作
//heapsize表示数组的长度
//设置左孩子的下标
int left = index*2+1;
//如果当前根节点还有叶节点,则操作
while(left < heapsize)
{
//两个孩子中,谁的值大,则把下标给largest
int largest = left + 1 < heapsize && a[left+1] > a[left]? left+1 : left;
//父和孩子之间的最大值谁最大,将下标给largest
largest = a[largest] > a[index] ? largest :index;
//如果最大值就是根节点,则退出
if(largest == index)
break;
//否则则交换
swap(a, index, largest);
index = largest;
left = index*2+1;
}
}
Dois, tipo de heap
Idéias:
1. Organize a matriz em uma estrutura de heap e forme um grande heap raiz por meio da operação heapInsert
2. Troque o nó na posição 0 do grande heap raiz pelo último nó, diminua o tamanho do heap em 1 e coloque o último elemento no heap na posição 0, execute a operação de heapify
3. Repita a etapa 2 até que o tamanho do heap seja 0 e a
animação da operação final seja exibida:
Código:
void heapify(vector<int>&a, int index1, int heapsize)
{
//进行heapifty
//设置左孩子的节点
int left = 2 * index1 + 1;
//如果有左孩子,则开始进行heapifty
while (left < heapsize)
{
//如果有右孩子,且右孩子的数值较大,则将右孩子的下标设置为largest
int largest = left + 1 < heapsize && a[left + 1] > a[left] ? left + 1 : left;
//比较根节点与较大孩子的数值,如果根节点大,则跳出循环
if (index1 == largest)
{
break;
}
//否则互换
swap(a, index1, largest);
//设置将最大值的下标赋值给index1,继续向下
index1 = largest;
left = 2 * index1 + 1;
}
}
void heapInsert(vector<int> &a, int index)
{
while (a[index] > a[(index - 1) / 2])
{
//两个元素互换
swap(a, a[index], a[(index - 1) / 2]);
//向上反馈
index = (index - 1) / 2;
}
}
void heapSort(vector<int> &a, int heapsize)
{
if (a.size() < 2)
return;
//将数组构建成大根堆
for (int i = heapsize-1; i >= 0; i--)
{
heapify(a, i, heapsize);
}
swap(a, 0, --heapsize);
while (heapsize>0)
{
//将变成大根堆的根节点与数组的最后一个数互换,并且将heapsize减小1
heapify(a, 0, heapsize);
swap(a, 0, --heapsize);
}
}
3. Extensão de classificação de heap
Uma matriz quase ordenada é conhecida. Quase ordenada significa que, se a matriz for organizada em ordem, cada elemento não pode se mover mais do que k, e k é relativamente pequeno em comparação com a matriz. Escolha um algoritmo de classificação apropriado para classificar esses dados.
Primeiro construímos um pequeno heap raiz com k elementos, porque a distância máxima de movimento é k, portanto, em casos extremos, use este método para colocar o nó raiz do pequeno heap raiz, ou seja, o valor mínimo em 0 e, em seguida, apontar para Em seguida, mova uma posição e, em seguida, coloque o elemento k na matriz abaixo no pequeno heap raiz para formar um pequeno heap raiz novamente e assim por diante. Por fim, exiba os números na pequena pilha de raiz de pequeno para grande.
Em C++, a camada inferior da operação multiconjunto é a estrutura da árvore binária.
void SortArrayDistanceLessK(vector<int> &a, int k)
{
//定义一个multiset容器
multiset<int> s;
//设置遍历的起始点
int index = 0;
//防止k超过数组长度,要限制传入multiset容器的元素数量
int c = a.size();
int b = min(c, k);
for (; index <= b; index++)
{
//将数组的前K个数依次传到multiset容器中
s.insert(a[index]);
}
int i = 0;
//依次将K后面的元素传入multiset容器中,并弹出第一个元素
for (; index < a.size(); index++)
{
//将k之后的元素一个一个压入到multiset中
s.insert(a[index]);
//将set的第一个元素放到数组的第一个位置,并将multiset容器第一个元素删除
set<int>::const_iterator it = s.begin();
a[i] = *it;
//删除第一个元素
s.erase(s.begin());
i++;
}
//将multiset容器中的数据以此弹出
while (!s.empty())
{
//将set的第一个元素放到数组的第一个位置,并将multiset容器第一个元素删除
set<int>::const_iterator it = s.begin();
a[i++] = *it;
//删除第一个元素
s.erase(s.begin());
}
}
4. Classificação de balde
Radix sort:
exemplo de código c++
#include <cmath>
int getDigit(int x, int d)
{
//返回所需位数的数值
return((x / (int)pow(10, d - 1)) % 10);
}
//桶排序
void radixSort(vector<int> &a, int L, int R, int digit)
//L:要排序的左区域
//R:要排序的右区域
//digit十进制的位数
{
//以十为基底
int radix = 10;
int i = 0, j = 0;
//设置辅助空间,其大小与数组大小一致
int *bucket = new int[R - L + 1];
//有多少位就进出桶多少次,开始入桶
for (int d = 1; d <= digit; d++)
{
//count[0]为当前位(d位)是0的数字有多少个
//count[1]为当前位(d位)是0-1的数字有多少个
//count[2]为当前位(d位)是0-2的数字有多少个
//count[i]为当前位(d位)是0-i的数字有多少个
//申请一个辅助数组,记录上面的数据
int *count = new int[radix];
//将申请的内存全部附初值0
for (int i = 0; i < radix; i++)
{
count[i] = 0;
}
//开始入桶操作
for (i = L; i <=R; i++)
{
j = getDigit(a[i], d);
count[j]++;
}
//对辅助数组处理成前缀和
for (i = 1; i < radix; i++)
{
count[i] = count[i] + count[i - 1];
}
//开始出桶操作
for (i = R; i >= L; i--)
{
j = getDigit(a[i], d);
bucket[count[j] - 1] = a[i];
count[j]--;
}
int j = 0;
for (i = L; i <= R; i++)
{
a[i] = bucket[j];
j++;
}
}
}
int maxbits(vector<int> &a)
{
//定义一个最大数值暂存变量
int largest = 0;
for (int i = 0; i < a.size(); i++)
{
largest = max(largest, a[i]);
}
//开始计算最大数值的十进制数一共有多少位
int res = 0;
while (largest != 0)
{
res++;
largest /= 10;
}
return res;
}
void radixSort(vector<int> &a)
{
if (a.size() < 2)
return;
radixSort(a, 0, a.size() - 1, maxbits(a));
}
5. A estabilidade e o resumo do algoritmo de classificação
Entre indivíduos de mesmo valor, se a ordem relativa não mudar devido à ordenação, a ordenação é estável; caso contrário, não é.
Ordenação sem estabilidade:
ordenação por seleção, ordenação rápida, ordenação por heap
ordenação com estabilidade:
ordenação por bolhas, ordenação por inserção, ordenação por mesclagem, ordenação sob a ideia de cada balde ordenação
não foi encontrada até agora Complexidade de tempo O(N*logN ), complexidade de espaço extra 0(1) e ordenação estável.
Perceber!
1. A complexidade de espaço adicional do merge sort pode ser O(1), mas é muito difícil e não precisa ser dominada. Se você estiver interessado, pode procurar por "método de cache interno do merge sort".
2. "Ordenação de mesclagem no local" fará com que a complexidade de tempo da ordenação de mesclagem se torne o(N^2
) 3. A ordenação rápida pode resolver problemas de estabilidade, mas é muito difícil e você não precisa dominá-la. procure por "01stable sort"
4 , todas as melhorias não são importantes, porque não há complexidade de tempo 0(N*logN), complexidade de espaço extra 0(1) e classificação estável.
5. Existe uma questão que coloca números ímpares no lado esquerdo da matriz e números pares no lado direito da matriz e exige que a ordem relativa original permaneça inalterada.É muito difícil encontrar esse problema.