<pre name="code" class="cpp">#include <iostream>
using namespace std;
class Solution{
public:
//冒泡排序
//比较相邻的两个元素,如果前面大于后面,则交换,每一轮过后,最大的那个数就放到了最后一个
//优化1:如果没有发生变化,那么证明已经是排好序了,则不需要再继续下一轮
//优化2:如果有100个数的数组,仅前面10个无序,后面90个都已排好序且都大于前面10个数字。记录第一次交换的位置即可。
void bubbleSort1(int A[],int n)
{
for(int i=0;i<n;i++)
for(int j = 1;j <n-i;j++)
if (A[j-1] > A[j])
swap(A[j-1],A[j]);
}
void bubbleSort2(int A[],int n)
{
bool flag = true;
int k = n;
while(flag)
{
flag = false;
for(int i = 1;i < k;i++)
{
if(A[i-1] > A[i])
{
swap(A[i-1],A[i]);
flag = true;
}
}
k--;
}
}
void bubbleSort3(int A[],int n)
{
int pos = n;
int k = n;
bool flag = true;
while(flag)
{
flag =false;
k = pos;
for(int i =1;i<k;i++)
{
if(A[i-1] > A[i])
{
swap(A[i-1],A[i]);
pos = i;
flag = true;
}
}
}
}
//直接插入排序
//将A[i],插入到[0,i-1]的有序空间,且保持有序。
//将A[i]于A[i-1]比较,如果A[i-1]小于A[i],啥也不做;否则,交换A[i-1]和A[i],j--,一直到A[i-1]小于A[i].
void insertSort(int A[],int n)
{
for(int i=0;i<n;i++)
for(int j=i-1;j>=0&&A[j]>A[j+1];j--)
swap(A[j],A[j+1]);
}
//希尔排序
//gap=n/2,每相隔gap个元素进行插入排序。gap=gap/2,再插入排序,直到gap=0;
//比如10个元素,gap为5.就分成了5组数据,每组元素为2.对每组进行插入排序。
//思路1,最紧扣定义的写法。
void shellSort1(int A[],int n)
{
for(int gap=n/2;gap>0;gap=gap/2)//步长
{
for(int i=0;i<gap;i++)//一共gap组数据
{
for(int j=i+gap;j<n;j+=gap)//对每组数据进行排序
{
if(A[j] < A[j-gap])
{
int k;
int tmp = A[j];//记录A[j]的值
for(k = j-gap;k>=0 && A[k] > tmp;k-=gap)
{
//比tmp大的数,则往后移位
A[k+gap] = A[k];
}
//此时A[k]是比tmp小的位置,则k+gap则是应该插入的位置
A[k+gap] = tmp;
}
}
}
}
}
//上面的思路代码量比较大。思路2.从gap元素开始,每个元素与组内的元素进行插入排序。
void shellSort2(int A[],int n)
{
for(int gap=n/2;gap>0;gap=gap/2)//步长
{
for(int i=gap;i<n;i++)
{
if(A[i] < A[i-gap])
{
int k;
int tmp = A[i];
for(k = i-gap;k >=0 && A[k]>tmp;k-=gap)
{
//比tmp大的,向后移位
A[k+gap]=A[k];
}
//此时A[k]比tmp小,插入位置在k+gap
A[k+gap] = tmp;
}
}
}
}
//思路3.用交换的思想,可以不用考虑向后移位的问题。
//如果A[i]>A[i-1],则不动;否则,交换,i--,再比较A[i]和A[i--],直到A[i]>A[i-1]为止。
void shellSort3(int A[],int n)
{
for(int gap = n/2;gap >0;gap/=2)
for(int i=gap;i<n;i++)
for(int j=i-gap;j>=0 && A[j]>A[j+gap];j-=gap)
swap(A[j],A[j+gap]);
}
//选择排序
//与插入排序类似,都分为有序区和无序区。不同的是,插入排序是将第一个元素插入有序区形成更大的有序区;而选择排序是从无序区找出最小,放到无序区的最前面(有序区的最后面)。
//最开始都是无序的,选择一个最小的与第一个交换;指向第二个,选择后面最小的与第二个交换。。。。
void selectSort(int A[],int n)
{
for(int i=0;i<n;i++)
{
int minIdx = i;
for(int j=i+1;j<n;j++)
{
if(A[j]<A[minIdx])
{
minIdx = j;
}
}
swap(A[i],A[minIdx]);
}
}
//归并排序
//递归+合并。当一个数组左边和右边有序,那么合并这两个有序数就完成了排序。如何让左右两遍都有序?用递归!递归下去,合并上来就是归并排序。
void mergeArray(int a[],int first,int mid,int last,int tmp[])//将两个有序数组a[first,mid]和a[mid,last]合并。
{
int i = first,j = mid +1;
int k=0;
while( i<=mid && j<=last )
{
if(a[i]<=a[j])
{
tmp[k++] = a[i++];
}
else
{
tmp[k++] = a[j++];
}
}
while(i <= mid)
{
tmp[k++] = a[i++];
}
while(j <= last)
{
tmp[k++] = a[j++];
}
for(i =0;i<k;i++)
{
a[first+i] = tmp[i];
}
}
void mergeSort(int a[],int first,int last,int tmp[])
{
if(first < last)
{
int mid = (first+last)/2;
mergeSort(a,first,mid,tmp);//左边有序
mergeSort(a,mid+1,last,tmp);//右边有序
mergeArray(a,first,mid,last,tmp);//将两个有序数列合并
}
}
//快速排序。挖坑填数字+分治法。
//1.i=first,j=last.选一个基准数(一般选第一个)。将其挖出来,形成一个坑a[i];
//2.从后向前j--找到一个比它小的数,找到后挖出来填到之前的a[i]的坑中,这时候形成一个新坑a[j];
//3.从前向后i++找到一个比它大的数,找到之后填到此前的a[j]坑中;
//4.重复,直到i==j,将基准数填入a[i]中。至此,基准点左边的都比它小,右边的都比它大。
//5.以基准点为中心,分成两个序列,重复上面的步骤。
void quickSort(int a[],int first,int last)
{
if(first < last)
{
int i=first,j=last,value=a[first];
while(i<j)
{
//从左边找到第一个小于value的数字,填到之前a[i]位置,形成一个新坑a[j]
while(i<j&&a[j]>value)
j--;
if(i<j)
a[i++] = a[j];
//从右边找到第一个大于value的数字,填到之前a[j]的位置上,形成一个新坑a[i]
while(i<j&&a[i]<value)
i++;
if(i<j)
a[j--]=a[i];
}
//将value填到a[i]中
a[i] = value;
//以基准点为中心分开为两个序列,重复上面步骤
quickSort(a,first,i);//递归处理
quickSort(a,i+1,last);
}
}
//堆排序
//二叉堆。父节点总是大于等于(小于等于)子节点。每一个左右子树都是一个二叉堆。父节点大于子节点的叫做最大堆,父节点小于子节点,叫做最小堆。
//二叉堆可以用数组表示。找父节点下标,(i-1)/2;左右子节点下标,2*i+1和2*i+2
//堆的插入。每次插入都是放到数组最后。它的父节点到根节点都是有序的,任务就是将新数据插入到有序数组中。(插入排序)
//堆的删除。每次删除第0个数据,然后将最后一个数据的值赋给根节点,自上向下调整树。相当于从根节点将一个数据下沉的过程。
//堆排序。1)首先堆化数组。2)A[0]与A[n-1]交换,再对A[0,n-2]重新恢复堆。第二次,将A[0]与A[n-2]交换,对[0,n-3]重新恢复堆,一直重复道A[0]与A[1]交换。
//这样每次最小的就放到了后面的有序序列。操作完成之后,整个数组就有序了。
//从第i个节点整理,从上到下。n为节点总数。
void heapFixDown(int a[],int i,int n)
{
int tmp = a[i];
int j = 2*i+1;//i的左子节点
while(j < n)
{
//先找到子节点中最小的
if(j+1 < n && a[j+1] < a[j])
{
j++;
}
//如果子节点中最小的都比根节点小,啥也不用做
if(a[j]>=tmp)
break;
//将较小的子节点往上移动,替换它的父节点
a[i] = a[j];
i=j;
j=2*i+1;
}
a[i]=tmp;
}
//建立最小堆
void createMinHeap(int a[],int n)
{
for(int i=n/2-1;i>=0;i--)
{
heapFixDown(a,i,n);
}
}
//堆排序
void heapSort(int a[],int n)
{
createMinHeap(a,n);
for(int i=n-1;i>=1;i--)
{
swap(a[i],a[0]);
heapFixDown(a,0,i);
}
}
};
void main()
{
int A[] = {7,2,3,5,9,8,10,20,15};
int n = sizeof(A)/sizeof(int);
printf("The original array is:\n");
for(int i=0;i<n;i++)
{
printf("%d ",A[i]);
}
printf("\n");
Solution *Sol = new Solution();
//Sol->bubbleSort3(A,n);
//Sol->selectSort(A,n);
//int *p = new int[n];
//if (p==NULL)
//return;
//Sol->mergeSort(A,0,n-1,p);
//delete[] p;
Sol->heapSort(A,n);
printf("The latest array is:\n");
for(int i=0;i<n;i++)
{
printf("%d ",A[i]);
}
printf("\n");
delete Sol;
}
各种排序
最新推荐文章于 2022-06-11 20:07:53 发布