各排序算法介绍与代码实现
目录
小贴士:
下面默认最小到大排序哦,可以根据需要修改。
默认以数组为例,也可以应用到链表和其他数据结构里呢!
选择排序
介绍
1.遍历一个数组,选出最小的一个放在第一个位置。
2.以第二到最后一个元素作为一个新数组,做同样的事。直到剩下一个元素。
代码
template<typename T2>
void sort(T2*p, int num) //p为数组首元素地址,num为元素数量
{
T2 t;
for (int i = 0; i < num - 1; i++)
for (int j = i + 1; j < num; j++)
{
if (p[i] > p[j])
t = p[i], p[i] = p[j], p[j] = t;
}
}
冒泡排序
介绍
1.两两比较数组元素,较大者后移一位,经过一轮遍历后,最大值则冒泡到最后一位。
2.以第一位到倒数第二位为一个新数组,做同样的事,知道剩下一个元素。
代码
template<typename T1>
void sort(T1*p, int num) //p为数组首元素地址,num为元素数量
{
T1 t;
for (int i = num - 1; i >= 1; i--)
for (int j = 0; j < i; j++)
if (p[j] > p[j+1])
t = p[j], p[j] = p[j + 1], p[j + 1] = t;
}
直接插入排序
介绍
1.以第一位元素为一个有序数组(只有一个元素的数组),把第二个元素按大小顺序插入指定位置,插入位之后的元素依次后移一位。
2.以第一和第二个元素作为一个有序数组,把第三个元素做同样的事情。以此类推,直到将最后一个元素插入按顺序插入指定位置。
代码
template<typename T2>
void insertion_sort(T2 a[], int n) {
int i, j;
T2 v;
for (i = 1; i<n; i++) {
for (v = a[i], j = i - 1; j >= 0 && v<a[j]; j--)
a[j + 1] = a[j];
a[j + 1] = v;
}
}
折半插入排序
介绍
直接插入排序是对有序数组进行遍历,以找到应插入的位置。而折半插入排序是使用二分法查找应插入的位置。可以节省时间,降低时间复杂度。
快速排序
基本思路:
1.以第一个元素为中间值,对数组进行遍历,将比这个中间值小的放在中间值的左边,同理,将比这个中间值大的放在它的右边。
2.将此中间值左右两边作为两个新数组,做同样的事情,直到左右两边没有元素或者只有一个元素。
其中一种实现方式(图文参考):
- 取第一个元素(begin)作为中间值。
- 分别定义
i
,j
两个下标。最开始i
为begin+1
,j
为最后一个元素。他们分别向中间移动。i
遇到大于中间值时停下,j
遇到小于中间值时停下,i
与j
处的值交换。 - 重复上一个步骤,直到
i=j
,将begin
与i(j)
处的值交换。
注意这个过程要先移动j
的下标,因为最终我们要将begin
与i(j)
处的值交换,begin
取的是第1个值,而比中间值小的数是要放在左边的。
直到这里,比中间值小的都放在了左边,比中间值大的都放在了右边。将左右两个部分重复这个过程,就排好序了。
void Quick_Sort(int *arr, int begin, int end){
if(begin > end)
return;
int tmp = arr[begin];
int i = begin;
int j = end;
while(i != j){
while(arr[j] >= tmp && j > i)
j--;
while(arr[i] <= tmp && j > i)
i++;
if(j > i){
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
arr[begin] = arr[i];
arr[i] = tmp;
Quick_Sort(arr, begin, i-1);
Quick_Sort(arr, i+1, end);
}
排序二叉树
介绍
1.以第一个元素作为根,遍历这个数组。将比根小的元素作为根的左孩子,比根大的作为根的右孩子。
2.遍历过程中若已有孩子占位,则以该孩子为根,进行递归。
#include<iostream>
using namespace std;
template<class ElemType>
void display(ElemType &e)
{
cout << e << " ";
}
template<class ElemType>
struct BinSortTreeNode{
ElemType data;
BinSortTreeNode *left, *right;
BinSortTreeNode()
{
left = right = NULL;
}
BinSortTreeNode(ElemType d, BinSortTreeNode *l = NULL, BinSortTreeNode *r = NULL)
{
data = d;
left = l;
right = r;
}
};
template<class ElemType>
class BinSortTree{
private:
BinSortTreeNode<ElemType> *root;
public:
BinSortTree()
{
root = NULL;
}
BinSortTreeNode<ElemType> *GetRoot()
{
return root;
}
void Insert(ElemType d, BinSortTreeNode<ElemType> *p)
{
BinSortTreeNode<ElemType> *temp = new BinSortTreeNode<ElemType>(d);
if (!temp)
{
cout << "内存申请失败" << endl;
exit(-1);
}
if (root == NULL)
{
root = temp; return;
}
if (p->data == d)
{
cout << "数据已存在!" << endl;
delete temp;
return;
}
if (d < p->data)
{
if (p->left == NULL)
{
p->left = temp; return;
}
Insert(d, p->left);
}
else
{
if (p->right == NULL)
{
p->right = temp; return;
}
Insert(d, p->right);
}
}
void PreTraverse(BinSortTreeNode<ElemType> *p, void visit(ElemType &e) = display)
{
if (p == NULL)
return;
visit(p->data);
PreTraverse(p->left);
PreTraverse(p->right);
}
void InTraverse(BinSortTreeNode<ElemType> *p, void visit(ElemType &e) = display)
{
if (p == NULL)
return;
InTraverse(p->left);
visit(p->data);
InTraverse(p->right);
return;
}
void PostTraverse(BinSortTreeNode<ElemType> *p, void visit(ElemType &e) = display)
{
if (p == NULL)
return;
PostTraverse(p->left);
PostTraverse(p->right);
visit(p->data);
}
bool Find_help(ElemType d, BinSortTreeNode<ElemType> *p)
{
if (p == NULL)
return false;
if (p->data == d)
return true;
return (Find_help(d, p->left) || Find_help(d, p->right));
}
void Find(ElemType d, BinSortTreeNode<ElemType> *p)
{
if (Find_help(d, root))
{
cout << "查找成功!" << endl; return;
}
cout << "查找失败!" << endl; return;
}
};
void main()
{
BinSortTree<int> B;
int e;
cout << "插入数据,-1结束:" << endl;
for (;;)
{
cin >> e;
if (e == -1)
break;
B.Insert(e, B.GetRoot());
}
cout << "先序遍历:"; B.PreTraverse(B.GetRoot()); cout << endl;
cout << "中序遍历:"; B.InTraverse(B.GetRoot()); cout << endl;
cout << "后序遍历:"; B.PostTraverse(B.GetRoot()); cout << endl;
cout << "请输入要查找的数:"; cin >> e;
B.Find(e, B.GetRoot());
cout << "请输入要查找的数:"; cin >> e;
B.Find(e, B.GetRoot());
}
堆排序
介绍
1.利用堆的特点,将所有元素最小值摘选出来。
2.将剩下的元素做同样的事情,最后即可得到从小到大的排序。
希尔排序
介绍
1.设置步长,假设此处步长为3。
2.将元素0,3,6,9……作为一个数组进行排序,排序算法可以自行选择。
3.将元素1,4,7,10……作为一个数组进行排序。
4.将元素2,5,8,11……作为一个数组进行排序。
5.步长减1,做同样的事情,直到步长为1,再做最后一次排序。
这个算法到最后数组基本有序,选择好算法可以一定程度上节省时间。
template<typename T3>
void shell_sort(T3 a[], int n, int d)
{
int i, j;
T3 temp;
for (; d >= 1; d = d -1 )
{
for (i = d; i < n; i++)
{
temp = a[i];
for (j = i - d; (j >= 0) && (a[j] > temp); j = j - d)
{
a[j + d] = a[j];
}
a[j + d] = temp;
}
}
}
归并排序
介绍
此算法将两个有序数组合并为一个数组
1.设置两个游标,分别指向两个数组的第一个元素。
2.取两个游标指向元素中的较小值,取出放在新数组中,此游标加1。
2.做同样的事情,直到一个数组已无元素,那么将另一个数组剩下的元素复制到新数组中即可。