内部/外部排序:内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。
算法的稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,则称这种排序算法是稳定的,否则称为不稳定的。
冒泡排序
思想:每次遍历不断交换最大值,排在最后一个。
void bubble_sort(vector<int> &nums){
for (int i = nums.size()-1; i>0; i--)
{
int count = 0;
for (int j = 0; j < i; j++)
{
if(nums[j]>nums[j+1])
{
swap(nums[j], nums[j+1]);
count++;
}
}
if(count==0)
break;
}
}
选择排序
思想:每次遍历选出一个最小一个,排在第一位。
void select_sort(vector<int> &nums){
for (int i = 0; i<nums.size()-1; i++)
{
int min_ind = i;
for (int j = i+1; j < nums.size(); j++)
{
if(nums[j]<nums[min_ind])
min_ind = j;
}
swap(nums[i], nums[min_ind]);
}
}
插入排序
思想:不断地从后面选一个数,插入到前面已经有序的序列里。
void insert_sort(vector<int> &nums){
for (int i = 1; i < nums.size();i++)
{
int t = nums[i];
int j = i;
for (; j > 0&&nums[j-1]>t;j--)
{
nums[j] = nums[j-1];
}
nums[j] = t;
}
}
希尔排序
思想:是插入排序的高效改进版本,先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。
void shell_sort(vector<int> & nums)
{
int n = nums.size();
int p = n / 2;
while(p)
{
for (int i = p; i < n;i++)
{
int j = i;
while(j-p>=0)
{
if(nums[j]<nums[j-p])
{
swap(nums[j],nums[j-p]);
j -= p;
}
else
break;
}
}
p = p / 2;
}
}
归并排序
思想:拆分到单个元素,然后两个两个往上进行递归合并。
void merge(vector<int> &nums, int begin, int mid, int end){
vector<int> left(nums.begin() + begin, nums.begin() + mid + 1);
vector<int> right(nums.begin() + mid+1, nums.begin() + end + 1);
int l = 0, r = 0;
int p = begin;
while(l+begin<=mid&&r+mid+1<=end)
{
if(left[l]<right[r])
nums[p++] = left[l++];
else
nums[p++] = right[r++];
}
while(l+begin<=mid)
nums[p++] = left[l++];
while(r+mid+1<=end)
nums[p++] = right[r++];
}
void merge_sort(vector<int> &nums, int begin, int end){
if(begin>=end)
return;
int mid = (end - begin) / 2 + begin;
merge_sort(nums, begin, mid);
merge_sort(nums, mid + 1, end);
merge(nums, begin, mid, end);
}
快速排序
思想:指定第一个数为 mid_value,排序使得 mid_value 左边的数比其小,右边的数比其大,然后分别对左边和右边进行递归排序。
void quick_sort(vector<int> &nums, int begin, int end){
if(begin>=end)
return;
int l = begin;
int r = end;
int t = nums[begin];
while(l<r)
{
while(l<r&&nums[r]>=t)
r--;
nums[l] = nums[r];
while(l<r&&nums[l]<=t)
l++;
nums[r] = nums[l];
}
nums[l] = t;
quick_sort(nums, begin, l-1);
quick_sort(nums, l+1, end);
}
堆排序
思想:建立一个大根堆,再依次把最大的数放到数组最后。
void ajust_heap(vector<int> & nums, int l, int x)
{
int maxn = nums[x];
int lx = x * 2 + 1;
int rx = x * 2 + 2;
if(lx<=l)
maxn = max(maxn, nums[lx]);
if(rx<=l)
maxn = max(maxn, nums[rx]);
if(maxn==nums[x])
return;
else if(lx<=l&&maxn==nums[lx])
{
swap(nums[x], nums[lx]);
ajust_heap(nums, l, lx);
}
else if(rx<=l&&maxn==nums[rx])
{
swap(nums[x], nums[rx]);
ajust_heap(nums, l, rx);
}
return;
}
void heap_sort(vector<int> & nums)
{
int l = nums.size() - 1;
for (int i = (l - 1) / 2; i >= 0;i--)
{
ajust_heap(nums, l, i);
}
for (int i = l; i > 0;i--)
{
swap(nums[0],nums[i]);
ajust_heap(nums, i-1, 0);
}
}
资料
数组中的第K个最大元素
堆排序实现:
class Solution {
private:
void adjust_heap(vector<int>& nums, int x){
int n=nums.size();
int mmax = nums[x];
int l=x*2+1;
int r=x*2+2;
if(l<n)
mmax=min(nums[l],mmax);
if(r<n)
mmax=min(nums[r],mmax);
if(mmax==nums[x])
return;
else if(l<n&&mmax==nums[l])
{
swap(nums[x],nums[l]);
adjust_heap(nums,l);
}
else if(r<n&&mmax==nums[r])
{
swap(nums[x],nums[r]);
adjust_heap(nums,r);
}
}
void build_heap(vector<int>& myheap){
for(int i=(myheap.size()-2)/2;i>=0;i--)
adjust_heap(myheap,i);
}
public:
int findKthLargest(vector<int>& nums, int k) {
vector<int> myheap(nums.begin(),nums.begin()+k);
build_heap(myheap);
for(int i=k;i<nums.size();i++)
if(nums[i]>myheap[0])
{
myheap[0]=nums[i];
adjust_heap(myheap, 0);
}
return myheap[0];
}
};