各排序算法介绍与代码实现

目录

  1. 选择排序
  2. 冒泡排序
  3. 直接插入排序
  4. 折半插入排序
  5. 快速排序
  6. 排序二叉树
  7. 堆排序
  8. 希尔排序
  9. 归并排序

小贴士:
下面默认最小到大排序哦,可以根据需要修改。
默认以数组为例,也可以应用到链表和其他数据结构里呢!

选择排序

介绍
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)作为中间值。
  • 分别定义ij两个下标。最开始ibegin+1j为最后一个元素。他们分别向中间移动。i遇到大于中间值时停下,j遇到小于中间值时停下,ij处的值交换。
  • 重复上一个步骤,直到i=j,将begini(j)处的值交换。

注意这个过程要先移动j的下标,因为最终我们要将begini(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.做同样的事情,直到一个数组已无元素,那么将另一个数组剩下的元素复制到新数组中即可。

posted @ 2019-04-14 11:27  NetRookieX  阅读(8)  评论(0编辑  收藏  举报