专升本之内部排序Word文件下载.docx
《专升本之内部排序Word文件下载.docx》由会员分享,可在线阅读,更多相关《专升本之内部排序Word文件下载.docx(16页珍藏版)》请在冰豆网上搜索。
voidInsertSort(T*array,intn){//array待排序数组,n:
数组元素数量
inti,j;
//循环变量
Ttemp;
//存储待排序元素
for(i=1;
i<
n;
i++){
j=i;
temp=array[i];
//待排序元素赋值给临时变量
while(j>
0&
&
temp<
array[j-1]){//当未达到数组的第一个元素或者待插入元素小于当前元素
array[j]=array[j-1];
//就将该元素后移
j--;
//下标减一,继续比较
}
array[j]=temp;
//插入位置已经找到,立即插入
}
}
算法分析:
若初始排序是随机的,则取最好的和最坏的平均情况,比较次数和移动次数都为n^2/4,时间复杂度O(n^2)理由:
假设被排序的数列中有n个数,遍历一趟的时间复杂度为O(n),遍历n-1遍,所以1+2+3+....(n-1)=n^2。
它是一个稳定的算法
折半插入排序
有一组数据待排序,排序区间为a[0]~a[n-1]。
分为有序区和无序区,初始时默认将a[0]为有序区,其余无序区。
而在有序区中,第一个元素为标识为first,最后一个元素为last。
排序思想:
1、取无序区的第一个元素a[i],mid=(first+last)/2;
2、将a[i]与a[mid]作比较,若a[i]<
a[mid],则在a[mid]左边比较,将last定义为a[mid-1](即a[mid]前一个元素),反之,则在a[mid]右边比较,将first定义为a[mid+1](即a[mid]后一个元素)。
重新取mid值。
3、重复操作2步骤。
IntbinaryInsertSort(intarr[]){
intlow,high,m,temp,i,j;
for(i=1;
i<
arr.length;
i++){
//折半查找应该插入的位置
low=0;
high=i-1;
while(low<
=high){
m=(low+high)/2;
if(arr[m]>
arr[i])
high=m-1;
else
low=m+1;
}
//统一移动元素,然后将这个元素插入到正确的位置
temp=arr[i];
for(j=i;
j>
high+1;
j--){
arr[j]=arr[j-1];
arr[high+1]=temp;
}}
最坏情况下(序列逆序)时间复杂度为O(N^2),最优情况下(初始顺序)时间复杂度为O(nlog2n),平均情况下时间复杂度为O(n^2)。
希尔排序(缩小增量排序),属于插入类的排序方法,时间效率上有着很大的改进
先将整个待排记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,在对全体记录进行一次直接插入排序。
例:
8,6,9,2,7,5,6,3,10
1)选择第一个增量gap=length/2=4,意味着可分为每隔4个数为一组;
2)每隔4个数为一组(同颜色的为一组),8,6,9,2,7,5,6,3,10。
对他们进行排序(组内比较),可得7,5,6,2,8,6,9,3,10。
取第二个增量(在第一个增量上在除2)gap=4/2=2,意味着每隔两个数为一组
3)分组之后可得7,5,6,2,8,6,9,3,10。
组内比较得6,2,7,3,8,5,9,6,10;
4)重复2步骤,gap=2/2=1,此时,整个数组为一组,6,2,7,3,8,5,9,6,10
publicComparable[]shellSort(Comparable[]array){
//从小到大排列
inth=1;
while(h<
array.length/3){
h=h*3+1;
while(h>
=1){
for(inti=h;
i<
array.length;
for(intj=i;
j>
=h&
array[j].compareTo(array[j-h])<
0;
j-=h){
Comparabletemp=array[j-h];
array[j-h]=array[j];
array[j]=temp;
h=h/3;
returnarray;
希尔排序对增量的旋转十分重要,最好的是每次除以2,最坏的时间复杂度为O(n^2),
3)掌握冒泡排序算法的思路、排序算法和算法分析,快速排序算法的思路、排序算法和算法分析
冒泡排序
算法思想:
比较两个相邻的元素,将值大的元素交换到右边
思路:
1)首先第一个记录的关键字和第二个记录的关键字进行比较,如果后面一个数比钱的数小,则将两个记录交换之,然后比较第二的记录和第三个记录,依次类推,直到第n-1个记录和第n个记录的关键字进行过比较为止,便完成了第一次冒泡,第一次冒泡将数据中的最大值排在最后面。
2)开始第二趟冒泡,从第一个元素到第n-1个元素进行步骤1排序,将前n-1个数据的最大值排在最后面(第n-1的位置)
3)重复步骤1,
IntbubbleSort(int*arr,intn){
intm,i,j;
for(i=0;
n-1;
i++)
for(j=0;
j<
n-1-i;
j++)
if(arr[j]>
arr[j+1])
{
m=arr[j];
arr[j]=arr[j+1];
arr[j+1]=m;
}
若初始状态为正序时,则只需进行一趟排序(进行n-1此比较,不进行移动),若为反序,则需进行n-1趟排序,n(n-1)/2次比较,n(n-1)/2次移动,总的时间复杂度为O(n^2),最好情况O(n),空间复杂度O
(1),是稳定的算法
快速排序
通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的小,则可分别对这两部分记录继续进行排序,已达到整个序列有序。
那么问题来了,如何才能使其中一部分的关键字比另一部分记录的小呢?
首先任意选一个记录(通常选择第一个记录)作为支点,通过支点和其他的关键字比较,小于支点的在一边,大于支点的在另一边。
不断的进行下去。
通常的具体做法:
附设两个指针Low和high,支点记录为pivotkey,
递归
voidquickSort(intarr[],intlow,inthigh)
{
intfirst=low;
intlast=high;
intkey=arr[first];
if(low>
=high)
return;
while(first<
last)
{
last&
arr[last]>
key)
last--;
arr[first]=arr[last];
arr[first]<
first++;
arr[last]=arr[first];
arr[first]=key;
quickSort(arr,low,first-1);
quickSort(arr,first+1,high);
非递归版本:
4)掌握简单选择排序算法的思路、排序算法和算法分析,堆排序算法的思路、排序算法和算法分析
简单选择排序和堆排序
都是内部排序中的选择排序
简单选择排序
在待排序的数据中选出最大(小)的元素放在最终的位置。
一趟简单选择排序的操作为:
通过n-i次关键字间的比较,从n-i+1个记录中选取关键字最小的记录,并和第i(1<
=i<
=n)个记录交换之。
一组数据95873245681475236991从大到小排序
1)用一个变量i指向数组的第一个位置也就是9,此时将0赋值给min,(注意,此时i是0,指向了数组的第一个位置9,但是a[i]=9)
2)用一个变量j指向i后一个位置,也就是5(j同i一样,仅仅是指向数组的第二个位置,所以j的值为1,但是a[j]=5);
3)然后5和9比较,9大,所以把j的值赋值给min(若前面的值更大,则将i赋值给min),j++;
4)然后j++重复步骤3,直到最后可以得到min=12(最后一个值的位置或者是数组长度),所以交换i和j的值,然后i++,接着循环;
IntselectSort(int[]arr){
for(inti=0;
arr.length-1;
intmin=i;
//记录最小元素位置
for(intj=i+1;
j<
arr.length;
j++){
if(arr[j]<
arr[min]){
min=j;
//更换最小元素位置
}
if(min!
=i){
swap(arr,i,min);
//与第i个位置进行交换
无论什么情况,比较的次数都是一样的((n-1)+(n-2)+。
。
+1)=n*(n-1)/2,交换的次数,最好的情况是0次,最坏的情况是n-1次,所以总的时间复杂度依然为O(n^2),虽然总的时间复杂度和冒泡排序一样,但是简单旋转排序的性能还是略好于冒泡排序。
时间复杂度:
(最好、最坏、平均)O(n^2),最好情况记录移动次数0,最坏情况记录移动次数3(n-1)
空间复杂度:
O
(1)
不稳定
堆排序
算法思路:
若在输出堆顶的最小值之后,使得剩余n-1个元素的序列重又建成一个堆,则得到n个元素中的次小值。
如此反复执行,便能得到一个有序序列,这个过程称之为堆排序。
voidma