数据结构与算法之排序(经典排序算法)
1、冒泡排序
代码分析:
这段代码实现了冒泡排序算法,其时间复杂度为 O ( n 2 ) O(n^2) O(n2)。冒泡排序是一种简单的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复地进行直到没有再需要交换的元素,也就是说该数列已经排序完成。
在这段代码中,bubbleSort函数中的外层循环执行了n次,内层循环执行了n-1次,因此总的时间复杂度为 O ( n 2 ) O(n^2) O(n2)。虽然冒泡排序的时间复杂度较高,但是它实现简单,对于小规模的数据排序效果还是不错的。
代码解读:
这段代码实现了冒泡排序算法。冒泡排序是一种简单的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复地进行直到没有再需要交换的元素,也就是说该数列已经排序完成。
在这段代码中,swap函数实现了两个元素的交换,bubble函数实现了一次冒泡排序,bubbleSort函数则是对整个数组进行冒泡排序。其中,bubble函数返回一个布尔值,表示是否进行了交换操作,如果没有进行交换操作,说明数组已经排好序了,可以直接退出循环。
在main函数中,首先输出了原始数组,然后调用bubbleSort函数对数组进行排序,最后输出排序后的数组。可以看到,排序后的数组是按照从小到大的顺序排列的。
值得注意的是,这段代码中使用了模板类,可以对不同类型的数组进行排序。同时,使用了STL中的foreach函数,可以方便地对数组进行遍历输出。文章来源:https://www.toymoban.com/news/detail-446414.html
#include <iostream>
#include <algorithm>
template<class T>
void swap (T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
template<class T>
bool bubble (T a[], int n)
{
bool swapped = false;
for (int i = 0; i < n - 1; ++i)
{
if (a[i] > a[i+1])//如果数组已经是排序的话,则排序就终止了
{
swap(a[i], a[i+1]);
swapped = true;
}
}
return swapped;
}
template<class T>
void bubbleSort(T a[], int n)
{
for (int i = n; i > 1 && bubble(a, i); --i); //最后只剩一个数字就是排好序的,故到a>1即可
}
void Show(const int& v)
{
std::cout << v << " ";
}
int main()
{
int arr[]{ 6, 5, 8, 4, 3, 1 };
for (auto x : arr)
std::cout << x << " ";
//std::for_each(arr, arr + sizeof(arr) / sizeof(int), Show);
std::cout << "\n";
bubbleSort(arr, sizeof(arr) / sizeof(int));
std::for_each(arr, arr + sizeof(arr) / sizeof(int), Show);
std::cout << std::endl;
return 0;
}
2、桶排序
#include<iterator>
#include<iostream>
#include<vector>
using std::vector;
/*****************
桶排序:将值为i的元素放入i号桶,最后依次把桶里的元素倒出来。
桶排序序思路:
1. 设置一个定量的数组当作空桶子。
2. 寻访序列,并且把项目一个一个放到对应的桶子去。
3. 对每个不是空的桶子进行排序。
4. 从不是空的桶子里把项目再放回原来的序列中。
假设数据分布在[0,100)之间,每个桶内部用链表表示,在数据入桶的同时插入排序,然后把各个桶中的数据合并。
*****************/
const int BUCKET_NUM = 10;
struct ListNode{
explicit ListNode(int i=0):mData(i),mNext(NULL){}
ListNode* mNext;
int mData;
};
ListNode* insert(ListNode* head,int val){
ListNode dummyNode;
ListNode *newNode = new ListNode(val);
ListNode *pre,*curr;
dummyNode.mNext = head;
pre = &dummyNode;
curr = head;
while(NULL!=curr && curr->mData<=val){
pre = curr;
curr = curr->mNext;
}
newNode->mNext = curr;
pre->mNext = newNode;
return dummyNode.mNext;
}
ListNode* Merge(ListNode *head1,ListNode *head2){
ListNode dummyNode;
ListNode *dummy = &dummyNode;
while(NULL!=head1 && NULL!=head2){
if(head1->mData <= head2->mData){
dummy->mNext = head1;
head1 = head1->mNext;
}else{
dummy->mNext = head2;
head2 = head2->mNext;
}
dummy = dummy->mNext;
}
if(NULL!=head1) dummy->mNext = head1;
if(NULL!=head2) dummy->mNext = head2;
return dummyNode.mNext;
}
void BucketSort(int n,int arr[]){
vector<ListNode*> buckets(BUCKET_NUM,(ListNode*)(0));
for(int i=0;i<n;++i){
int index = arr[i]/BUCKET_NUM;
ListNode *head = buckets.at(index);
buckets.at(index) = insert(head,arr[i]);
}
ListNode *head = buckets.at(0);
for(int i=1;i<BUCKET_NUM;++i){
head = Merge(head,buckets.at(i));
}
for(int i=0;i<n;++i){
arr[i] = head->mData;
std::cout << arr[i] << " ";
head = head->mNext;
}
std::cout << std::endl;
}
int main()
{
int a[] = {56, 89, 24, 6, 18, 5, 1, 99, 63};
BucketSort(sizeof(a)/sizeof(int), a);
return 0;
}
3、插入排序
#include <iostream>
#include <algorithm>
template<class T>
void insert(T a[], int n, const T& x)
{
int i;
for (i = n - 1; i >= 0 && x < a[i]; --i)
a[i + 1] = a[i];
a[i + 1] = x;//因为退出for循环之后i已经减了1
}
template<class T>
void insertionSort(T a[], int n)
{
for (int i = 1; i < n; ++i)
{
T t = a[i];
insert(a, i, t);//依次插入到恰好比下一个数字小的地方
}
}
void Show(const int& v)
{
std::cout << v << " ";
}
int main()
{
int arr[]{ 6, 5, 8, 4, 3, 1 };
for (auto x : arr)
std::cout << x << " ";
//std::for_each(arr, arr + sizeof(arr) / sizeof(int), Show);
std::cout << "\n";
insertionSort(arr, sizeof(arr) / sizeof(int));
std::for_each(arr, arr + sizeof(arr) / sizeof(int), Show);
std::cout << std::endl;
return 0;
}
4、归并排序
递归版:
//完整代码
#include <iostream>
using namespace std;
template<typename T>
void merge_sort_recursive(T arr[], T reg[], int start, int end) {
if (start >= end)
return;
int len = end - start, mid = (len >> 1) + start;
int start1 = start, end1 = mid;
int start2 = mid + 1, end2 = end;
merge_sort_recursive(arr, reg, start1, end1);
merge_sort_recursive(arr, reg, start2, end2);
int k = start;
while (start1 <= end1 && start2 <= end2)
reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
while (start1 <= end1)
reg[k++] = arr[start1++];
while (start2 <= end2)
reg[k++] = arr[start2++];
for (k = start; k <= end; k++)
arr[k] = reg[k];
}
//整數或浮點數皆可使用,若要使用物件(class)時必須設定"小於"(<)的運算子功能
template<typename T>
void merge_sort(T arr[], const int len) {
T *reg = new T[len];
merge_sort_recursive(arr, reg, 0, len - 1);
delete[] reg;
}
void showAges(const int& age)
{
std::cout << age << '\t';
}
void Test1()
{
int ages[] = { 10, 9, 45, 30, 28, 90, 38, 30, 30, 45, 45 };
merge_sort(ages, sizeof(ages) / sizeof(int));
std::cout << "The sorted ages is:\n";
for (auto x : ages)
showAges(x);
// std::cout << x << '\t';
}
int main()
{
Test1();
return 0;
}
迭代版:
//完整代码
#include <iostream>
using namespace std;
/*****************
迭代版
*****************/
//整數或浮點數皆可使用,若要使用物件(class)時必須設定"小於"(<)的運算子功能
template<typename T>
void merge_sort(T arr[], int len) {
T* a = arr;
T* b = new T[len];
for (int seg = 1; seg < len; seg += seg) {
for (int start = 0; start < len; start += seg + seg) {
int low = start, mid = min(start + seg, len), high = min(start + seg + seg, len);
int k = low;
int start1 = low, end1 = mid;
int start2 = mid, end2 = high;
while (start1 < end1 && start2 < end2)
b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++];
while (start1 < end1)
b[k++] = a[start1++];
while (start2 < end2)
b[k++] = a[start2++];
}
T* temp = a;
a = b;
b = temp;
}
if (a != arr) {
for (int i = 0; i < len; i++)
b[i] = a[i];
b = a;
}
delete[] b;
}
void showAges(const int& age)
{
std::cout << age << '\t';
}
void Test1()
{
int ages[] = { 10, 9, 45, 30, 28, 90, 38, 30, 30, 45, 45 };
merge_sort(ages, sizeof(ages) / sizeof(int));
std::cout << "The sorted ages is:\n";
for (auto x : ages)
showAges(x);
// std::cout << x << '\t';
}
int main()
{
Test1();
return 0;
}
5、快速排序
#include <iostream>
#include <algorithm>
#include <exception>
#include <cstdlib>
#include <ctime>//time
template<class T>
void swap(T* a, T* b)//注意用指针构造交换函数时,交换的是指针指向的值
{
T temp = *a;
*a = *b;
*b = temp;
}
int RandomInRange(int st, int en)
{
srand(unsigned(time(0)));//把当前时间作为随机数种子
return st + rand() % (en - st + 1);
}
int Partition(int data[], int length, int start, int end)
{
if (data == nullptr || length <= 0 || start < 0 || end >= length)
{
throw "Invalid Parameters";
}
int index = RandomInRange(start, end);
swap(&data[index], &data[end]);
int small = start - 1;
for (index = start; index < end; ++index)
{
if (data[index] < data[end])//当条件不成立时index增加,small不变
{
++small;
if (small != index)
swap(&data[index], &data[small]);
}
}
++small;
swap(&data[small], &data[end]);
return small;//返回的结果是左边比data[end]小,右边比data[end]大的数
}
void QuickSort(int data[], int length, int start, int end)
{
if (start == end)
return;
//**********************************这部分是判断数组是否已经按升序排好序,排好的话就直接终止,这样就防止出现最糟糕的情况
bool sorted = true; //《剑指offer》p81
for (int i = start; i < end; ++i)
{
if (data[i] > data[i + 1])//如果数组已经是排序的话,则排序就终止了
{
sorted = false;
}
}
if (sorted)
return;
//****************************************************************************************
int index = Partition(data, length, start, end);
if (index > start)
QuickSort(data, length, start, index - 1);
if (index < end)
QuickSort(data, length, index + 1, end);
}
void Show(const int& v)
{
std::cout << v << " ";
}
int main()
{
int arr[]{ 6, 5, 8, 4, 3, 1 };
for (auto x : arr)
std::cout << x << " ";
//std::for_each(arr, arr + sizeof(arr) / sizeof(int), Show);
std::cout << "\n";
QuickSort(arr, sizeof(arr) / sizeof(int), 0, sizeof(arr) / sizeof(int) - 1);
std::for_each(arr, arr + sizeof(arr) / sizeof(int), Show);
return 0;
}
6、选择排序
#include <iostream>
#include <algorithm>
template<class T>
void swap (T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
template<class T>
void selectionSort(T a[], int n)
{
bool sorted = false;
for (int size = n; !sorted && (size > 1); size--)
{
int indexOfMax = 0;
sorted = true;
for (int i = 1; i < size; ++i)
{
if (a[indexOfMax] <= a[i])
indexOfMax = i;
else
sorted = false;//无序的
}
swap (a[indexOfMax], a[size - 1]);//如果是无序的,则每次循环将最大值放在最后一位
}
}
void Show(const int& v)
{
std::cout << v << " ";
}
int main()
{
int arr[]{ 6, 5, 8, 4, 3, 1 };
for (auto x : arr)
std::cout << x << " ";
//std::for_each(arr, arr + sizeof(arr) / sizeof(int), Show);
std::cout << "\n";
selectionSort(arr, sizeof(arr) / sizeof(int));
std::for_each(arr, arr + sizeof(arr) / sizeof(int), Show);
return 0;
}
桶排序的一个示例(《剑指offer》中的一个问题)
后面会补充剑指offer相关的内容文章来源地址https://www.toymoban.com/news/detail-446414.html
#include <iostream>
#include <exception>
void SortAges(int ages[], int length)
{
if (ages == nullptr || length <= 0)
return;
const int oldestAge = 99;
int timesOfAge[oldestAge + 1];
for (int i = 0; i < oldestAge; ++i)
timesOfAge[i] = 0;
for (int i = 0; i < length; ++i)
{
int age = ages[i];
if (age < 0 || age > oldestAge)
throw new std::exception("age out og range");
++timesOfAge[age];
}
int index = 0;
for (int i = 0; i <= oldestAge; ++i)
{
for (int j = 0; j < timesOfAge[i]; ++j)
{
ages[index] = i;
++index;
}
}
}
void showAges(const int& age)
{
std::cout << age << '\t';
}
void Test1()
{
int ages[] = { 10, 9, 45, 30, 28, 90, 38, 30, 30, 45, 45 };
SortAges(ages, sizeof(ages) / sizeof(int));
std::cout << "The sorted ages is:\n";
for (auto x : ages)
showAges(x);
// std::cout << x << '\t';
}
int main()
{
Test1();
return 0;
}
到了这里,关于数据结构与算法之排序(更新中。。。)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!