简单选择排序
void SelectSort(int arr[],int n)
{
for(int i=0;i<n-1;i++)
{
j=SelectMinKey(arr,i,n);
swap(arr[i],arr[j])
}
}
void SelectMinKey(int arr[],int k,int n)
{
int min=arr[k];
int pos=k;
for(int i=k+1;i<n;i++)
{
if(arr[i]<min)
{
min=arr[i];
pos=i;
}
}
return pos;
}
总结
树形选择排序
说明
- 减少比较次数
- 时间复杂度为nlogn
- 缺点:需要辅助存储空间较多
- 赢者树:赢得是较小的树,父节点保存较小的节点的下标
void TreeSelectSort(int arr[],int n)
{
int size=2*n-1;
int *tree=(int *)malloc(sizeof(int)*size);
int k=size/2;
for(int i=0;i<n;i++)
{
tree[k++]=arr[i];
}
int curpos=size/2-1;
Play(tree,size,curpos);
i=0;
arr[i]=tree[tree[0]];
tree[tree[0]]=MAXVALUE;
for(int i=0;i<n;i++)
{
curpos=(tree[0]-1)/2;
Select(tree,size,curpos);
arr[i]=tree[tree[0]];
tree[[tree[0]]=MAXVALUE;
}
free(tree);
tree=NULL;
}
void Play(int tree[],int n,int p)
{
int left,right;
int leftvalue,rightvalue;
while(p>=0)
{
left=2*p+1;
right=2*p+2;
leftvalue=getvalue(tree,n,left);
rightvalue=getvalue(tree,n,right);
if(leftvalue<=rightvalue)
{
if(left<n/2)
{
tree[p]=tree[left];
}
else
{
tree[p]=left;
}
}
else
{
if(right<2/n)
{
tree[p]=tree[right];
}
else
{
tree[p]=right;
}
}
p--;
}
}
int getvalue(int tree[],int n,int p)
{
if(p>=n)
return MAXVALUE;
int value;
if(p<n/2)
{
value=tree[tree[p]];
}
else
{
value=tree[p];
}
}
void Select(int tree[],int n,int p)
{
int i=p;
int j=2*p-1;
int leftvalue,rightvalue;
int falg=-1;
while(flag&&i>=0)
{
leftvalue=getvalue(tree,n,j);
rightvalue=getvalue(tree,n,j+1);
if(leftvalue<=rightvalue)
{
if(j<n/2)
{
tree[i]=tree[j];
}
else
{
tree[i]=left;
}
}
else
{
if(j+1<2/n)
{
tree[i]=tree[j+1];
}
else
{
tree[i]=right;
}
}
if(i==0)
flag++;
i=(i-1)/2;
j=2*i+1;
}
}
总结
- 树形选择排序先要初始化树,再从最后一个分支开始比较,找到最小的数值,然后只需要比较其父节点即可,将上一次找到的最小值设为最大值就不受影响了
- 分支节点中保存的不是比较后的数据而保存的是他们在树中的下标
堆排序算法
说明
- 每一个父节点都大于其子节点成为大堆;每一个父节点都小于其左右子树称为小堆
void HeapSort(int arr[],int n)
{
int*heap=(int*)malloc(sizeof(int)*n);
for(int i=0;i<n;i++)
{
heap[i]=arr[i];
}
int curpos=n/2-1;
while(curpos>=0)
{
siftDown(heap,n,curpos);
curpos--;
}
for(int i=0;i<n;i++)
{
arr[i]=RemoveMinKey(heap,n-i-1);
}
}
void RemoveMinKey(int heap[],int n)
{
int key=heap[0];
heap[0]=heap[n];
siftDown(heap,n,0);
return key;
}
void siftDown(int heap[],int n,int p)
{
int i=p;
int j=2*i+1;
while(j<n)
{
if(j<n-1&&heap[j]>heap[j+1])
j++;
if(heap[i]<=heap[j])
break;
else
{
swap(heap[i],heap[j]);
i=j;
j=2*i+1;
}
}
free(p);
p=NULL;
}
总结
- 对数据较小时不适合使用
- 效率高,最高不超过nlogn
- 所需空间较少