理论篇链接↓↓↓
插入排序-希尔排序-选择排序-冒泡排序-快速排序-基数排序-外部排序-归并排序[数据结构与算法]
插入排序
- 简单说就三步 定位-》挤空-》插入
- 从无序序列中的选择第一个插入到有序序列
- 时间复杂度就是 最好0(n)最坏0(n^2)平均0(n ^ 2).空间复杂度0(1)
- 比较次数不固定 看代码就知道
# include<string.h>
# include<stdio.h>
#include <algorithm>
# include<vector>
# include<iostream>
using namespace std;
void straisort(vector<int>& vec )
{
int i,j;
int temp;
int n=vec.size();
for(i=1;i<n;i++)
{
temp =vec[i];
j=i-1;
while(j >= 0 && temp<vec[j])
{
vec[j+1]=vec[j];
j--;
}
vec[j+1]=temp;
}
}
int main(void)
{
int a[]={ 2,5,1,5,3,7,5,7,5,6 };
vector<int> test(a,a+sizeof(a)/sizeof(a[0]));
straisort(test);
for (int i = 0; i < 10; i++) {
cout << test[i] << " ";
}
return 0;
}
- 2021-09-17:取出无序第一个插入到有序 for嵌套while实现
希尔排序
- 插入排序的改进,
- 宏观调整最后微观调整(逐步有序)
- i 和 i+step的比较,步长逐步减少到1
# include<string.h>
# include<stdio.h>
#include <algorithm>
# include<vector>
# include<iostream>
using namespace std;
void shellsort(vector<int>& vec )
{
int step,i;
int n= vec.size();
step = n/3+1;
for( step ; step>0 ;step--)
{
for(i=0 ; i+step<n ;i++ )
{
if(vec[i] > vec[i+step])
{
swap(vec[i],vec[i+step]);
}
}
}
}
int main(void)
{
int a[]={ 2,5,1,5,3,7,5,7,5,6 };
vector<int> test(a,a+sizeof(a)/sizeof(a[0]));
shellsort(test);
for (int i = 0; i < 10; i++) {
cout << test[i] << " ";
}
return 0;
}
- 2021-09-17复习:记住步长的设置 内层for
- 思想简单,就是一个逐步有序
冒泡排序
- 两两比较,每次把最大的移到后面,设置flat标志位 在最外层
- 比较次数固定,时间复杂度0(n ^ 2)
# include<string.h>
# include<stdio.h>
#include <algorithm>
# include<vector>
# include<iostream>
using namespace std;
void bubble_sort(vector<int>& vec)
{
int size = vec.size();
if (size <= 1) return;
int flat = 1;
for (int i = 0; i < size && flat == 1; i++)
{
flat = 0;
for (int j = 1; j < size - i; j++)
{
if (vec[j - 1] > vec[j])
{
swap(vec[j - 1], vec[j]);
flat = 1;
}
}
}
}
int main(void)
{
int a[] = { 2,5,1,5,3,7,5,7,5,6 };
vector<int> test(a, a + sizeof(a) / sizeof(a[0]));
bubble_sort(test);
for (int i = 0; i < 10; i++) {
cout << test[i] << " ";
}
return 0;
}
- 补充第二种写法,外循环决定趟数 内循环比较 每次少一个数
归并排序
#include<iostream>
using namespace std;
#include<vector>
vector <int> t(20);
void merge_sort(int* a,int l,int r){
if (l==r) return;
int mid=(l+r)/2;
merge_sort(a,l,mid);
merge_sort(a,mid+1,r);
int i=l;
int j=mid+1;
for (int k=l; k<=r; k++)
{
if ( (j>r) || (a[i]<=a[j] && i<=mid ) )
{
t[k]=a[i];
i++;
} else
{
t[k]=a[j];
j++;
}
}
for (int k=l; k<=r; k++) a[k]=t[k];
}
int main()
{
int arr[] = { 2,8,23,10,4,1,6,7 };
int L = 0;
int R = 7;
merge_sort(arr, L, R);
for (int i = 0; i <= R; i++)
{
cout << arr[i] << endl;
}
return 0;
}
- 第二个版本 把数组作为参数传入 不再作为全局变量
a[i]<=a[j] && i<=mid
容易写错
#include<iostream>
using namespace std;
#include<vector>
/ector <int> t(20);
void merge_sort(vector<int>& a,int l,int r,vector<int>& t)
{
if (l==r) return;
int mid=(l+r)/2;
merge_sort(a,l,mid,t);
merge_sort(a,mid+1,r,t);
int i=l;
int j=mid+1;
for (int k=l; k<=r; k++)
{
if ( (j>r) || (a[i]<=a[j] && i<=mid ) )
{
t[k]=a[i];
i++;
} else
{
t[k]=a[j];
j++;
}
}
for (k=l; k<=r; k++) a[k]=t[k];
}
int main()
{
int arr[] = { 2,8,23,10,4,1,6,7 };
vector<int> arr_new(arr,arr+sizeof(arr)/sizeof(arr[0]));
int L = 0;
int R = 7;
vector <int> t(arr_new.size());
merge_sort(arr_new, L, R , t);
for (int i = 0; i <= R; i++)
{
cout << arr_new[i] << endl;
}
return 0;
}
#include<iostream>
using namespace std;
#include<vector>
void merge_sort(int* a, int l, int r)
{
if (l == r) return;
int mid = (l + r) / 2;
merge_sort(a, l, mid);
merge_sort(a, mid + 1, r);
int i = l;
int j = mid + 1;
vector<int> vec;
for (int k = l; k <= r; k++)
{
if ((j > r) || a[i] <= a[j] && i <= mid)
{
vec.push_back(a[i]);
i++;
}
else
{
vec.push_back(a[j]);
j++;
}
}
int n = 0;
for (int k = l; k <= r; k++) a[k] = vec[n++];
}
- 补充了第三种写法,没什么大的区别 小的修改,归并是先序+后序,在后序处理需要定义 i j k 三个变量。for循环内进行判断,只有两种情况 放入左边数据 还是放入 右边的数据 。不要忘记终止条件
快速排序
- 一个就是while嵌套的判断也要加上i<j
- 第二个就是 s[i]=s[j];忘记i++ 要记得移到下一个判断点,或者理解成被填入的位置前进
- 第三个就是 s[i] = x; 最后要把枢纽放入i下标
- 第四个就是 quickSort(s, i + 1, r); 不是(s,i,r)
- 第五从右边判断开始 因为第一个需要填入的是左边
- 不要忘记 if (i<j)因为要确保不是因为越界才跳出循环 确保是因为找到第一个符合的值(补充)
#include<iostream>
using namespace std;
void quickSort(int s[], int l, int r)
{
if (l>= r)
{
return;
}
int i = l, j = r, x = s[l];
while (i < j)
{
while(i < j && s[j]>= x)
j--;
if(i < j && s[j]<x )
{
s[i]=s[j];
i++;
}
while(i < j && s[i]< x)
i++;
if(i < j)
{
s[j]=s[i];
j--;
}
}
s[i] = x;
quickSort(s, l, i - 1);
quickSort(s, i + 1, r);
}
int main()
{
int array[]={34,65,12,43,67,5,78,10,3,70},k;
int len=sizeof(array)/sizeof(array[0]);
cout<<"The orginal arrayare:"<<endl;
for(k=0;k<len;k++)
cout<<array[k]<<",";
cout<<endl;
quickSort(array,0,len-1);
cout<<"The sorted arrayare:"<<endl;
for(k=0;k<len;k++)
cout<<array[k]<<",";
cout<<endl;
system("pause");
return 0;
}
- 2021-09-17 其实就是思考一个序列怎么分成两个部分 挖出一个空,保存值为 x ,再加上两个指针 i 和 j
选择排序
- 就是每次选择最小的
- 时间复杂度0(n ^ 2),比较的个数是固定的
- 需要注意的一个临时变量存放最小值坐标
- 每一趟的初始最小值 和 实际最小值
# include<string.h>
# include<stdio.h>
# include<vector>
# include<iostream>
using namespace std;
void selectsort(vector<int>& vec )
{
int i,j,k;
int n=vec.size();
for(i = 0;i<n;i++)
{
k = i;
for(j = i+1;j<n;j++)
{
if(vec[k]>vec[j])
{
k = j;
}
}
if(k != i)
{
swap(vec[k],vec[i]);
}
}
}
int main(void)
{
int a[]={ 2,5,1,5,3,7,5,7,5,6 };
vector<int> test(a,a+sizeof(a)/sizeof(a[0]));
selectsort(test);
for (int i = 0; i < 10; i++) {
cout << test[i] << " ";
}
return 0;
}
计数排序
- 这个比较简单,就不放在这边了
- 构建一个数组,下标表示数值,元素表示频率,第一次循环放入构建的数组
- 第二次循环遍历输出,频率–
堆排序
- 大堆顶 根结点是最大值 的堆,用于维护和查询 max、
- 第 i 个结点的 父结点 下标 为 (i-1)/2 ;
- 第 i 个结点的 左子结点 下标 为 2i+1 ;
- 第 i 个结点的 右子结点 下标 为 2i+2 ;
- 最后一个非叶子结点 下标为:n/2 -1(也可以理解成 最后一个节点坐标是 n-1 带入第一个公式 就是 (n-2)/2)
- 思想就是: 将一个长为n的序列构造成一个大顶堆,则整个序列的最大值就是堆顶的根结点。 将最大值结点与末尾结点的值互换,此时末尾结点的值就是最大值。(即数组的最后一个元素为最大值) 。然后将剩余的 n-1个序列重新构造成一个大顶堆,再将n-1序列的最大值与末尾结点的值互换,就会得到 次最大值。 如此重复执行,就可以得到一个有序序列了。
局部调整向下,从后向前建立(右下)
#include<iostream>
#include <algorithm>
using namespace std;
void heapify(int* tree, int n, int i)
{
if (i >= n) return;
int c1 = i * 2 + 1;
int c2 = i * 2 + 2;
int max = i;
if (c1<n && tree[c1]>tree[max])
{
max = c1;
}
if (c2<n && tree[c2]>tree[max])
{
max = c2;
}
if (max != i)
{
swap(tree[max],tree[i]);
heapify(tree,n,max);
}
}
void build_heap(int *tree, int n)
{
int last_node = n - 1;
int parent = (last_node - 1) / 2;
for (int i =parent; i>=0; i--)
{
heapify(tree,n,i);
}
}
void heap_sort(int *tree, int n)
{
build_heap(tree,n);
for (int i = n-1; i>=0; i--)
{
swap(tree[i], tree[0]);
heapify(tree,i,0);
}
}
int main()
{
int tree[] = { 7,10,15,30,35,23,40 };
int n = 7;
heap_sort(tree,n);
for (int i=0;i<n;i++)
{
cout << tree[i]<<" ";
}
cout<< endl;
return 0;
}