赞
踩
1.掌握选择排序、冒泡排序、合并排序、快速排序、插入排序算法原理。
2.掌握不同排序算法时间效率的经验分析方法,验证理论分析与经验分析的一致性。
原理:从未排序的数据元素中选出最小的一个元素,放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小元素,继续放在起始位置,直到未排序元素个数为0。
算法分析:整个算法是双重循环:
外循环控制排序的趟数,对n个记录进行排序的趟数为n-1趟;
内循环控制每一趟的排序,进行第i趟排序时,所需的比较次数总是n-i次,关键字比较次数KCN 与记录的初始排列无关。
总的关键字比较次数为
记录移动次数RMN与初始排列有关,最好的情况是,排列已经有序,则RMN=0;最坏情况是,每一趟都要进行交换,总的记录移动次数为 RMN = 3(n-1)。
时间复杂度是O(n2),空间复杂度是O(1)。
选择排序是一种不稳定的排序方法。
原理:对于n个待排序记录,从第1个记录起,依次比较相邻两个记录的关键字,如果发生逆序,则交换之,直至第n-1个记录和第n个记录比较完,循环n-1次即可排列有序。
算法分析:
最好情况:在记录的初始序列正序时,只执行一趟起泡排序,做n-1次关键字比较,但是不移动记录。
最坏情况:记录的初始序列逆序时,要执行n-1趟冒泡,第i趟做n-i次关键字比较,执行n-i次记录交换,比较次数KCN和交换次数RCN为:
冒泡排序的时间复杂度为O(n2)。
冒泡排序是一种稳定的排序方法。
原理:归并是指将两个或两个以上的有序序列合并成一个有序序列。
2-路归并排序:
其核心是如何将相邻的两个子序列归并成一个子序列。
算法分析:
(1)假设待归并的两个有序表长度分别为m和n,若是顺序存储,则归并后,都会利用一个长度为m+n的数组作为辅助数组用于保存合并序列,则空间复杂度为O(m+n)
(2)归并操作至多只需要m+n次移位和m+n次比较,因此归并的时间复杂度为O(m+n)
(3)如果待排序的记录为n个,则需要做(int)(log2n)趟2-路归并排序,每趟2-路归并排序的时间复杂度为O(n),因此2-路归并排序的时间复杂度为O(nlog n)。
(4)需要额外空间,大小与待排序记录空间相同,则空间复杂度为O(n)。
(5)归并排序是一种稳定的排序方法。
原理:任取待排序记录序列中的某个记录作为枢轴(也称为基准、锚点或支点记录,pivot), 通过一趟排序,将待排序记录以枢轴为界分割成两部分,其中,比枢轴关键字小的记录都在枢轴的前面,而枢轴后面的记录都比枢轴关键字大。然后,采用同样方法再分别对这两部分子序列进行排序,最后达到整个序列有序。
算法分析:时间复杂度是O(nlog n),空间复杂度是:S(n)=O(㏒n)。
快速排序是一种不稳定的排序方法。
原理:将待排序的记录依次插入到已排好序的序列中,得到一个新的、记录数增加1的有序表。 直到所有的记录都插入完为止。
算法分析:
关键字比较次数和记录移动次数与记录的初始排列有关。
时间复杂度为O(n2),空间复杂度为O(1)。
最大的优点是简单,在记录数较少时,是比较好的办法。
插入排序是一种稳定的排序方法。
当n=10000时
当n=20000时
当n=30000时
当n=40000时
当n=50000时
表格如下
图像如下
在大数据量进行排序时,冒泡排序需要耗费大量时间,选择排序和插入排序所耗费时间略少,合并排序和快速排序耗费时间最少。
在大数据量排序情况下,理论值大于实际值不少,原因是基准值n=10000时平均运行时间较长。
在大数据量排序情况下,理论值和实际值较为相似;理论值略小于实际值的原因是基准值n=10000时平均运行时间较少。
在大数据量排序情况下,理论值和实际值较为接近。
在大数据量排序情况下,理论值和实际值较为相似,且快速排序的平均运行时间少,效率高。
在大数据量排序情况下,理论值和实际值几乎一致。
算法思想:将十亿分块,每个块为十万,用选择排序将每个块最大的十个数进入队列,最后再统一取出找出最大的十个数即为最终所求。
最终结果
综合上述实验可得,当数据规模相当大时,选择排序、冒泡排序、插入排序耗费的时间相当多,该类算法虽然简单易懂,但是效率较低,不适合处理大量数据。合并排序和快速排序采用了分治、递归的思想,运行大量数据时效率仍然非常高,远胜于前面的几种排序算法。因此,当数据规模较大时,选择后面两种排序算法为佳。
- #include<iostream>
- #include<algorithm>
- #include<stdlib.h>
- #include<queue>
- using namespace std;
-
- int n; //数据总数
- int* zu;
- queue<int> q;
-
- int select()//选择排序
- {
- int qi, zhi; //记录起止时间
- qi = clock();
-
- //
- for (int i = 0; i < n; i++)
- {
- int min = 99999,minpos;
-
- for (int j = i; j < n; j++)
- if (zu[j] < min)//找到最小值放到前面
- {
- min = zu[j];
- minpos = j;
- }
-
- if (i != minpos)
- swap(zu[i], zu[minpos]);//交换
- }
- //
-
- zhi = clock();
- return zhi - qi; //返回时间差
- }
-
- int bubble()//冒泡排序
- {
- int qi, zhi; //记录起止时间
- qi = clock();
-
- //
- int i, j;
- for (i = 0; i < n - 1; i++)
- for (j = 0; j < n-i-1; j++)
- if (zu[j] > zu[j + 1])
- swap(zu[j], zu[j + 1]);
- //
-
- zhi = clock();
- return zhi - qi; //返回时间差
- }
-
- void merge(int* a, int l, int mid, int r)//合并两序列
- {
- int* b = new int[r - l + 1];
- int i = l, j = mid + 1, k = 0;
-
- while (i <= mid && j <= r)
- {
- if (a[i] <= a[j])
- b[k++] = a[i++];
- else
- b[k++] = a[j++];
- }
- while (i <= mid)
- b[k++] = a[i++];
- while (j <= r)
- b[k++] = a[j++];
-
- for (i = l,k=0; i <= r; i++)//将排序好的序列传回去
- a[i] = b[k++];
- }
-
- void mergesort(int *a,int l,int r)//递归进行归并排序
- {
- if (l < r)
- {
- int mid = (l + r) / 2;
- mergesort(a, l, mid);
- mergesort(a, mid + 1, r);
- merge(a, l, mid, r);
- }
- }
-
- int guibing()//归并排序
- {
- int qi, zhi; //记录起止时间
- qi = clock();
-
- //
- mergesort(zu, 0, n - 1);
- //
-
- zhi = clock();
- return zhi - qi; //返回时间差
- }
-
- int part(int l,int r)//划分子表并返回轴的位置
- {
- int zhou = zu[l];//保存轴的值
- while (l < r)
- {
- while (l < r && zhou <= zu[r])//注意'='不能漏掉
- r--;
- zu[l] = zu[r];
-
- while (l < r && zhou >= zu[l])
- l++;
- zu[r] = zu[l];
- }// 循环结束的条件是l==r
-
- zu[l] = zhou;//将轴的值放入l==r的位置
- return l; //返回轴的位置
- }
-
- void qsort(int l, int r)
- {
- int zhoupos;
- if (l < r)
- {
- zhoupos = part(l, r);
- qsort(l, zhoupos - 1);
- qsort(zhoupos + 1, r);
- }
- }
-
- int quick()//快速排序
- {
- int qi, zhi; //记录起止时间
- qi = clock();
-
- //
- qsort(0, n - 1);
- //
-
- zhi = clock();
- return zhi - qi; //返回时间差
- }
-
- int insert()//插入排序
- {
- int qi, zhi; //记录起止时间
- qi = clock();
-
- //
- int i, j;
- for (i = 1; i < n; i++)//第一个数据不用插入
- {
- int temp = zu[i];
- for (j = i; j > 0; j--)
- {
- if (temp < zu[j - 1])
- zu[j] = zu[j - 1];
- else
- break;
- }
- zu[j] = temp;
- }
- //
-
- zhi = clock();
- return zhi - qi; //返回时间差
- }
-
- void show()//输出函数
- {
- for (int i = 0; i < n; i++)
- {
- cout << zu[i] << " ";
- }
- cout << endl;
- }
-
- void ceshi(int ci, int size)//测试次数和排序数组大小
- {
- n = size;
- zu=new int[size];//动态建立数组
- srand(time(0));
- int t1,t2,t3,t4,t5, i, j;
- t1 = t2 = t3 = t4 = t5 = 0;
-
- /*
- for (i = 0; i < ci; i++)
- {
- for (j = 0; j < size; j++)
- zu[j] = rand();
- //show();//1
- t1+= select();
- t2 += bubble();
- t3 += guibing(); 不能放一起,要分开!!!!!
- t4 += quick();
- t5 += insert();
- //show(); cout << endl;//2 语句1和2用来测试排序算法是否正确,此时n要取小值
- }
- */
-
- for (i = 0; i < ci; i++)
- {
- for (j = 0; j < size; j++)
- zu[j] = rand();
- t1 += select();
- }
-
- for (i = 0; i < ci; i++)
- {
- for (j = 0; j < size; j++)
- zu[j] = rand();
- t2 += bubble();
- }
-
- for (i = 0; i < ci; i++)
- {
- for (j = 0; j < size; j++)
- zu[j] = rand();
- t3 += guibing();
- }
-
- for (i = 0; i < ci; i++)
- {
- for (j = 0; j < size; j++)
- zu[j] = rand();
- t4 += quick();
- }
-
- for (i = 0; i < ci; i++)
- {
- for (j = 0; j < size; j++)
- zu[j] = rand();
- t5 += insert();
- }
-
- cout << "选择排序的平均运行时间为" << t1 / ci << "ms" << endl;
- cout << "冒泡排序的平均运行时间为" << t2 / ci << "ms" << endl;
- cout << "合并排序的平均运行时间为" << t3 / ci << "ms" << endl;
- cout << "快速排序的平均运行时间为" << t4 / ci << "ms" << endl;
- cout << "插入排序的平均运行时间为" << t5 / ci << "ms" << endl;
- }
-
- void selectshiyi()//选择排序从10亿中找最大的10个
- {
- int i,j,k,l;
- srand(time(0));
- zu = new int[100000];
- k = 0;
- n = 100000;
- for (i = 0; i < 1000000000; i++)//将十亿分块,每个块为十万,将每个块最大的十个数进入队列,最后再统一取出找出最大的十个数
- {
- zu[k++] = rand();
- if (k == 99999) //每次数组存满十万则进行操作
- {
- for (l = 0; l < 10; l++)
- {
- int max = -1, maxpos;
-
- for (j = 0; j < n; j++)
- if (zu[j] > max)//找到最大值
- {
- max = zu[j];
- maxpos = j;
- }
- q.push(zu[maxpos]);//进入队列
- zu[maxpos] = 0;
- }
- k = 0;
- }
- }
-
- n = 10000;
- for (i = 0; i < n; i++)//取出队列中的值
- {
- zu[i] = q.front();
- q.pop();
- }
-
- for (l = 0; l < 10; l++)//将最大的十个数存入队列
- {
- int max = -1, maxpos;
-
- for (j = 0; j < n; j++)
- if (zu[j] > max)
- {
- max = zu[j];
- maxpos = j;
- }
- q.push(zu[maxpos]);
- zu[maxpos] = 0;
- }
-
- for (i = 0; i < 10; i++)//输出
- {
- cout << q.front() << " ";
- q.pop();
- }
- cout << endl;
- }
-
- int main()
- {
- /*
- for (int i = 1; i <= 5; i++)
- {
- cout << endl << endl;
- int size = i*10000; //设置数组大小
- cout << "排序数组大小n=" << size << endl;
- ceshi(20, size); //测试20次
- }
- */
- selectshiyi();
- }

(by 归忆)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。