一转眼2月过去了,秋招快结束了,趁现在这段时间对之前面试中问到的排序算法做一个小结,怕背熟练的又忘记了。。。
#include<Windows.h>
#include<iostream>
#include<vector>
#include<stdio.h>
#include<stack>
using namespace std;
void maopao(vector<int> &a)//时间复杂度O(n^2),空间复杂度O(1),稳定排序
{
if (a.empty()) return;
int n = a.size();
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
if (a[i] > a[j])
{
swap(a[i], a[j]);
}
}
}
}
void maopao1(vector<int> &a)//变种1 设立标志位,当标志位在一轮循环中不变时说明数组已经有序
{
if (a.empty()) return;
int n = a.size();
for (int i = 0; i < n; i++)
{
bool flag = false;
for (int j = i + 1; j < n; j++)
{
if (a[i] > a[j])
{
swap(a[i], a[j]);
flag = true;
}
}
if (!flag) break;
}
}
void kuaipai(vector<int> &a,int left,int right)//递归版本,时间复杂度O(nlongn),最好情况O(n),最差情况O(n^2),辅助情况(O(n)) 非稳定排序
{
if (left > right) return;
int i = left; int j = right; int k = a[i];
while (i < j)
{
while (i < j&&a[j] >= k)
{
j--;
}
if (i < j) a[i++] = a[j];
while (i < j&&a[i] < k)
{
i++;
}
if (i < j) a[j--] = a[i];
}
a[i] = k;
kuaipai(a, left, i-1);
kuaipai(a, i + 1, right);
}
int post(vector<int> &a, int left, int right)//非递归版本
{
int i = left; int j = right; int k = a[i];
while (i < j)
{
while (i < j&&a[j] >= k)
{
j--;
}
if (i < j) a[i++] = a[j];
while (i < j&&a[i] < k)
{
i++;
}
if (i < j) a[j--] = a[i];
}
a[i] = k;
return i;
}
void kuaipai1(vector<int> &a,int i ,int j)
{
stack<int> t;
t.push(i);
t.push(j);
int k;
while (!t.empty())
{
int r = t.top(); t.pop();
int l = t.top(); t.pop();
k = post(a, l, r);
if (k-1 > l)
{
t.push(l);
t.push(k - 1);
}
if (k + 1 < r)
{
t.push(k + 1);
t.push(r);
}
}
}
void xuanpai(vector<int> &a)//时间复杂度O(n^2),额外空间O(1),不稳定排序
{
for (int i = 0; i < a.size(); i++)
{
int min = i;
for (int j = i+1; j < a.size(); j++)
{
if (a[j] < a[min])
{
min = j;
}
}
if(min!=i)swap(a[i], a[min]);
}
}
void charu(vector<int> &a)//直接插入排序,时间复杂度O(N^2),空间复杂度O(1),稳定排序
{
for (int i = 1; i < a.size(); i++)
{
int j = i;
while (j > 0 && a[j] < a[j - 1])
{
swap(a[j], a[j - 1]);
j--;
}
}
}
void xier(vector<int> &a)//空间复杂度O(nlongn)~O(n^2),空间复杂度O(1),不稳定排序
{
for (int gap = a.size() / 2; gap > 0; gap /= 2)
{
for (int i = gap; i < a.size(); i++)
{
int j = i;
while (j - gap >= 0 && a[j] < a[j - gap])
{
swap(a[j], a[j - gap]);
j--;
}
}
}
}
void merge(vector<int> &a, int l, int mid, int r)
{
int i = l;
int j = mid + 1;
int t = 0;
vector<int> temp(r - l + 1, 0);
while(i <= mid&&j <= r)
{
if (a[i] <= a[j])
{
temp[t++] = a[i++];
}
else {
temp[t++] = a[j++];
}
}
while (i <= mid) { temp[t++] = a[i++]; }
while (j <= r) { temp[t++] = a[j++]; }
t = 0;
while (t < (r - l + 1)) { a[l+t] = temp[t]; t++; }//a[l+t]=temp[t++] 数组下标访问越界?
}
void guibin(vector<int> &a,int l,int r)//时间复杂度O(nlogn),空间复杂度O(n),稳定排序
{
if (l < r)
{
int mid = (r+l) / 2;
guibin(a, l, mid);
guibin(a, mid + 1, r);
merge(a, l, mid, r);
}
}
void adjustHeap(vector<int> &a, int i, int length)
{
int temp = a[i];
for (int k = 2 * i + 1; k < length; k = 2 * k + 1)//从i结点的左子结点开始,2*i+1开始
{
if (k + 1 < length&&a[k] < a[k + 1])//如果左子节点小于右子节点,k指向右子节点
{
k++;
}
if (a[k] > temp)//如果子节点的值大于父节点,将子节点的值赋给父节点
{
a[i] = a[k];
i = k;
}
else break;
}
a[i] = temp;
}
void duipai(vector<int> &a)//时间复杂度O(nlogn),空间复杂度O(1),不稳定排序
{
//建立大顶堆
for (int i = a.size() / 2 - 1; i >= 0; i--)
{
//从第一个非叶子结点从下至上,从右至左调整结构
adjustHeap(a, i, a.size());
}
//调整堆结构+交换堆顶元素与末尾元素
for (int j = a.size() - 1; j > 0; j--)
{
swap(a[0],a[j]);//将堆顶元素与末尾元素交换
adjustHeap(a, 0, j);//重新对堆调整
}
}
int main(void)
{
vector<int> a = { 2,6,3,1,5,8,4,2,0 };
duipai(a);
for (int i = 0; i < a.size(); i++)
{
cout << a[i] ;
}
cout << endl;
system("pause");
return 0;
}
以上代码均在vs2015下跑过,亲证可用。