时间:2019年7月8日
排序算法
堆排序
堆是树的一种特殊形式
1.要满足完全二叉树(定义要知道吧) 儿子要从左边开始
像这样的就不满足!
2.父节点的值要大于子节点
heapify(将树变成堆的过程)
关于完全二叉树的一些性质
对于此树 进行堆排序
#include<stdio.h>
void swap(int tree[],int n,int i)
{
int temp=tree[n];
tree[n]=tree[i];
tree[i]=temp;
}
//n表示树的结点总个数 i表示当前的结点位置
void heapify(int tree[],int n,int i)
{
if(i>=n){
return ;
}
int c1= 2*i+1;
int c2= 2*i+2;
int max=i; //max表示最大值的结点位置
if(c1<n && tree[max]<tree[c1])
{
max=c1;
}
if(c2<n && tree[max]<tree[c2])
{
max=c2;
}
// (tree[max]<tree[c1])?(c1):(tree[max]<tree[c2])?max=c2:max=max;
if(max!=i) //说明i指的不是树的最大值
{
swap(tree,max,i);
heapify(tree,n,max);
}
}
int main()
{
int tree[]={4,10,3,5,1,2};
int n=6;
heapify(tree,n,0);
for(int i=0;i<n;i++)
{
printf("%d\n",tree[i]);
}
return 0;
}
打印的结果
#include<stdio.h>
//数组中要交换数据 可以通过交换其结点坐标来实现
void swap(int tree[],int n,int i)
{
int temp=tree[n];
tree[n]=tree[i];
tree[i]=temp;
}
//heapify 把一颗普通树变成堆(堆中的第一个结点的值是最大的)
//n表示树的结点总个数 i表示当前的结点位置
void heapify(int tree[],int n,int i)
{
if(i>=n){
return ;
}
int c1= 2*i+1;
int c2= 2*i+2;
int max=i; //max表示最大值的结点位置
if(c1<n && tree[max]<tree[c1])
{
max=c1;
}
if(c2<n && tree[max]<tree[c2])
{
max=c2;
}
if(max!=i) //说明i指的不是树的最大值
{
swap(tree,max,i);
heapify(tree,n,max);
}
}
void build_heap(int tree[],int n)
{
int last_node = n-1;
int parent = (last_node - 1)/2;
int i;
for(i=parent;i>=0;i--)
{
heapify(tree,n,i);
}
}
void heap_sort(int tree[],int n)
{
build_heap(tree,n);
int i;
for(i=n-1;i>=0;i--)
{
swap(tree,i,0);//将第一个结点和最后一个结点进行交换
heapify(tree,i,0);
}
}
int main()
{
int tree[]={4,10,3,5,1,2};
int n=6;
/* heapify(tree,n,0);
*/
heap_sort(tree,n);
for(int i=0;i<n;i++)
{
printf("%d\n",tree[i]);
}
return 0;
}
大概的流程
快速排序
在时间上比冒泡排序好,在空间上比桶排序好
平均时间复杂度为O(NlogN)
代码:
#include<stdio.h>
int arr[]={2,5,1,6,3};
int a[]={2,5,1,6,3};
int len=5;
void quick_sort(int left,int right) //本人习惯让最后一个数作为基准数
{
if(left>right)
{
return ;
}
int i=left;
int j=right;
int index=arr[right];
int temp;
while(i!=j)
{
while(arr[i]<=index&&i<j){
i++;
}
while(arr[j]>=index&&i<j){
j--;
}
if(i<j)
{
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
arr[right]=arr[i];
arr[i]=index;
quick_sort(left,i-1);
quick_sort(i+1,right);
}
void quicksort(int left,int right)
{
int i,j,t,temp;
if(left>right)
return;
temp=a[left]; //temp中存的就是基准数
i=left;
j=right;
while(i!=j)
{
//顺序很重要,要先从右往左找
while(a[j]>=temp && i<j)
j--;
//再从左往右找
while(a[i]<=temp && i<j)
i++;
//交换两个数在数组中的位置
if(i<j)//当哨兵i和哨兵j没有相遇时
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
//最终将基准数归位
a[left]=a[i];
a[i]=temp;
quicksort(left,i-1);//继续处理左边的,这里是一个递归的过程
quicksort(i+1,right);//继续处理右边的,这里是一个递归的过程
}
int main()
{
quick_sort(0,len-1);
for(int i=0;i<len;i++)
{
printf("%d ",arr[i]);
}
quicksort(0,len-1);
printf("\n");
for(int i=0;i<len;i++)
{
printf("%d ",a[i]);
}
return 0;
}
归并排序
#include<stdio.h>
int arr[]={2,8,9,10,4,5,6,7};
int m=4;
int l=0;
int r=7;
int min(int n,int m)
{
return (n<=m)?n:m;
}
void merge(int m,int l,int r)
{
int left_size=m-l;
int right_size=r-m+1;
int left[left_size];
int right[right_size];
int i,j,k;
//填充左边的数组
for(i=l;i<m;i++)
{
left[i-l]=arr[i];
}
//填充右边的数组
for(i=m;i<=r;i++)
{
right[i-m]=arr[i];
}
//合并到原来的数组
i=0;
j=0; k=0;
while(i<left_size&&j<right_size)
{
if(left[i]<=right[j]){
arr[k]=left[i];
i++;k++;
}else{
arr[k]=right[j];
j++;k++;
}
}
while(i<left_size)
{
arr[k]=left[i];
i++;k++;
}
while(j<right_size)
{
arr[k]=right[i];
j++;k++;
}
}
int main()
{
merge(m,l,r);
for(int i=0;i<=r;i++)
{
printf("%d ",arr[i]);
}
return 0;
}