整理关于排序算法的相关知识点
冒泡排序
冒泡排序(Bubble sort),是一种简单的排序算法。
它重复地循环要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
算法步骤
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
void Sort1(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
for (int j = 0; j < a.length - 1; j++) {
if (a[j] > a[j + 1]) {
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
}
void BubbleSort()
{
int j,exchange, bound, temp;
exchange = length-1;
while(exchange != 0)
{
bound = exhange;
exchange = 0;
for (j = 0lj < bound; j+)
if (data[j] > data[j+1]) {
temp = data[j];
data[j] = data[j+1];
data[j+1] = temp;
exchange = j;
}
}
}
插入排序
直接插入排序是插入排序中最简单的排序方法,其基本思想是:依次将待排序序列中的每一个记录到已排好序的序列中,直到全部记录都排好序。
排序步骤:
1.将整个待排序的记录排序分成有序区和无序区,初始时有序区为待排序记录序列的第一个记录,无序区包括所有剩余待排序的记录;
2. 将无序区的第一个记录插入到有序区的合适位置中,从而使无序区减少一个记录,有序区增加一个记录;
3.重复执行步骤2,直到无序区没有记录为止。
void InsertSort()
{
int i, j, temp;
for (i = 1;i < length;i++)
{
temp = data[i];
for (j = i-1; j >= 0 && temp < data[j]; j--)
data[j+1] = data[j];
data[j+1] = temp;
}
}
拓朴排序
对一个有向图构造拓朴序列的过程称为拓朴排序,并且一个AOV网的拓朴排序可能不唯一。
1.图的存储结构:因为在拓朴排序的过程中,需要查找所有以某点为尾的弧,既需要找到该顶点的所有出边,所以,图应该采用邻接表存储。
2.查找没有前驱的结点:为了避免每次查找时都去遍历顶点表,设置一个栈,凡是AOV网中入度为0的顶点都将其压栈。
过程示例:
部分代码:
void TopSort( )
{
int i, j, k, count = 0; //累加器count初始化
int S[MaxSize], top = -1; //采用顺序栈并初始化
EdgeNode *p = nullptr;
for (i = 0; i < vertexNum; i++) //扫描顶点表
if (adjlist[i].in == 0) S[++top] = i; //将入度为0的顶点压栈
while (top != -1 ) //当栈中还有入度为0的顶点时
{
j = S[top--]; //从栈中取出入度为0的顶点
cout << adjlist[j].vertex << "\t";
count++;
p = adjlist[j].firstEdge; //工作指针p初始化
while (p != nullptr) //描顶点表,找出顶点j的所有出边
{
k = p->adjvex;
adjlist[k].in--;
if (adjlist[k].in == 0) S[++top] = k; //将入度为0的顶点入栈
p = p->next;
}
}
if (count < vertexNum ) cout << "有回路";
}
C++Sort函数
Sort函数使用模板:
Sort(start,end,排序方法)
I)Sort函数包含在头文件为#include<algorithm>的c++标准库中,调用标准库里的排序方法可以不必知道其内部是如何实现的,只要出现我们想要的结果即可!
II)Sort函数有三个参数:
(1)第一个是要排序的数组的起始地址。
(2)第二个是结束的地址(最后一位要排序的地址)
(3)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序。
其他排序算法
选择排序
简单选择排序是选择排序中最简单的排序方法,其基本思想是:第i趟排序在待排序序列中选取最小的记录,并和第i个记录交换作为有序序列的第一个记录
过程:
1.将整个记录序列划分为有序区和无序区,初始时有序区为空,无序区含有待排序的所有记录。
2. 在无序区中选取最小的记录,将它与无序区中的第一个记录交换,使得有序区增加一个记录,同时无序区减少一个记录。
3.不断重复步骤2,直到无序区只剩下一个记录。
void selectSort()
{
int i, j, index, temp;
for(i = 0; i < length-1; i++)
{
index = i;
for (j = i+1; j < length; j++)
if (data[j] < data[index])
index = j;
if (index != i) {
temp = data[i];
data[i] = data[index];
data[index] = temp;
}
}
}
希尔排序
希尔排序是对直接插入排序的一种改进,改进的着眼点:1:若待排记录基本有序,直接插入排序的效率很高2:由于直接插入排序算法简单,则在待排序记录个数较少时效率也很高。
基本思想是:先将整个待排序记录序列分割成若干个子序列,在子序列内分别进行直接插入排序,带整个序列基本有序时,在对全体记录进行一次直接插入排序。
部分代码:
void ShellSort()
{
int d, i, j, temp;
for(d = length/2; d >= 1; d = d/2)
{
for ( i = d; i < length; i++)
{
temp = data[i];
for ( j = i-d; j >= 0 && temp < data[j]; j = j-d)
data[j+d] = data[j];
data[j+d] = temp;
}
}
}
快速排序
快速排序是对起泡排序的一种改进。
基本思想:首先选定一个轴值,将待排序记录划分成两部分,左侧记录均小于或等于轴值,右侧记录均大于或等于轴值,然后对这两部分重复上述过程直到整个序列有序。显然,快速排序是一个递归过程。
代码块
int Partition(int first,in last)
{
int i = first, j = last, temp;
while(i < j)
{
while (i < j && data[i] < = data[j])
j--;
if ( i < j) {
temp = data[i];
data[i] = data[j];
daa[j] = temp;
i++;
}
while (i < j && data[i] <= data[j])
i++;
if ( i < j) {
temp = data[i];
data[i] = data[j];
data[j] = temp;
j--;
}
}
return i;
}
void QucikSort(int first, int last)
{
if (first >= last)
return ;
else {
int pivot = Partition(first, last);
QuickSort(first, pivot-1);
QuickSort(pivot+1,last);
}
}
堆排序
堆排序是简单选择排序的一种改进
基本思想:
首先将待排序序列调整成一个堆,选出堆中所有记录的最大值,然后将堆顶记录移走,并将剩余记录在调整成堆,这样有找出了次大记录,依此类推,直到堆中只有一个记录。
void Sift(int k, int last)
{
int i, j, temp;
i = k; j = 2 * i + 1;
while (j <= last)
{
if (j < last && data[j] < data[j+1])
j++;
if (data[i] > data[j])
break;
else {
temp = data[i];
data[i] = data[j];
data[j] = temp;
i = j;
j = 2 * i + 1;
}
}
}
void HeapSort()
{
int i, temp;
for (i = cei(length/2)-1; i >= 0; i--)
Sift(i, length-1);
for ( i = 1; i < length; i++)
{
temp = data[0];
data[0] = ata[length-i];
data[length-i] = temp;
Sift(0,length-i-1);
}
}