1、插入排序
原理:插入排序顾名思义将当先元素插入到其本应在的位置,其他的元素依次向后移(自己实现的时候忘记了移动元素),如下动图所示。时间复杂度:,这里是最大时间复杂度,有些时候时间复杂度会大大降低(高度有序序列的情况下)。
template <typename T>
void insertSort(T arr[],int n){
for(int i = 0;i < n;i++){
int temp = arr[i];
int j = i;
for(;arr[j-1] > temp&&j >= 1;j--){
//记住这里还要有移位操作
arr[j] = arr[j-1];
}
std::swap(arr[j],temp);
}
}
2、选择排序
每次选择最大的元素作为当前位置的元素。时间复杂度。
算法原理:
- 首先选择最大(小)的元素放在序列的第一位
- 在剩余的元素中选择最大(小)的元素凡在齐次
- 重复1、2直到完全有序
template <typename T>
void bubbleSort(T arr[],int n){
int j,min;
for(int i = 0;i < n;i++){
min = i;
for(j = i + 1;j < n;j++){
if(arr[min] > arr[j])
min = j;
}
std::swap(arr[i],arr[min]);
}
}
3、冒泡排序
算法原理:按大小交换相邻两个元素的顺序,每一次排序就会确定一个最大(小)值
template <typename T>
void bubbleSort(T arr[],int n){
for(int i = 0;i < n;i++){
for(int j = 0;j < n-i-1;j++){
if(arr[j] > arr[j+1])
std::swap(arr[j],arr[j+1]);
}
}
}
4、归并排序(稳定nlogn,但需要额外内存)
1、递归
void __merge(T arr[], int l, int mid, int r){
// 经测试,传递aux数组的性能效果并不好
T aux[r-l+1];
for( int i = l ; i <= r; i ++ )
aux[i-l] = arr[i];
int i = l, j = mid+1;
for( int k = l ; k <= r; k ++ ){
if( i > mid )
{ arr[k] = aux[j-l];
j ++;
}
else if( j > r ){//一定要else if
arr[k] = aux[i-l];
i ++;
}
else if( aux[i-l] < aux[j-l] )
{ arr[k] = aux[i-l];
i ++;
}
else
{ arr[k] = aux[j-l];
j ++;
}
}
}
void mergesort(int arr[],int l,int r){
if(l >= r)
return;
int mid = l + (r-l)/2;
mergesort(arr,l,mid);
mergesort(arr,mid+1,r);
_merge(arr,l,mid,r);
}
2、非递归
void mergesort(int arr[],int n){
for(int sz = 1;sz < n;sz += sz)
for(int i = 0;i + sz -1< n;i += sz+sz){
_merge(arr,i,i+sz-1,min(n-1,i+sz+sz-1));
}
}
5、DFS算法
滑雪问题:
int skidfs(int map[][],bool mark[][],int i,int j,int n){
int k;
if(mark[i][j])
return mark[i][j];
if(map[i][j] > map[i-1][j] && i - 1 >= 0){
k = skidfs(map,mark,i-1,j,n) + 1;
if(k > mark[i][j])
mark[i][j] = k;
}
if(map[i][j] > map[i][j-1] && j - 1 >= 0){
k = skidfs(map,mark,i,j-1,n) + 1;
if(k > mark[i][j])
mark[i][j] = k;
}
if(map[i][j] > map[i+1][j] && i + 1 <= n){
k = skidfs(map,mark,i+1,j,n) + 1;
if(k > mark[i][j])
mark[i][j] = k;
}
if(map[i][j] > map[i][j+1] && j + 1 <= 0){
k = skidfs(map,mark,i,j+1,n) + 1;
if(k > mark[i][j])
mark[i][j] = k;
}
return mark[i][j];
}
void skisolution(int n){
int output = 0;
int step = 1;
int map[n][n];
int mark[n][n] = {0};
//bool mark[n][n] = {false};//最开始使用的是true的方式来记录点有没有被访问过但是对于
//本题不适用,因为同一个可能要被访问多次
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
step = skidfs(map,mark,i,j,n);
if(step > output)
output = step;
}
}
std::cout<<output<<std::endl;
}
dfs算法步骤:
1.1、有单一起点的:
int main(){
dfs();
}
1.2、多种可能起点的:
int main(){
for:
for:
dfs();
}
void dfs(){
//终止条件判断1、最小路径需要判断是否最小了2、如果需要打印路径这里判断是否到终点,到终点后打印操作
//不超越边界or没被访问过、操作过;
dfs();
//有时候在归来的时候需要去除标记
}
5、迷宫路径问题
int rows = 5,cols = 6;
int count = 0;
int map[5][6] = {{0,1,0,0,0,1},{0,0,0,1,0,0},{1,0,1,0,0,1},{1,0,0,1,0,1},{1,1,0,0,0,0}};
bool mark[5][6] = {false};
stack<pair<int,int>> stk;
void dfs(int x,int y){
int index[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
if(x == rows-1 && y == cols-1){
stack<pair<int,int>> temp;
cout << "******************path"<< ++count << "******************" << endl;
while(!stk.empty()){
pair<int,int> pt = stk.top();
stk.pop();
temp.push(pt);
}
while(!temp.empty()){
pair<int,int> p2 = temp.top();//栈是先进后出,但是打印的得时候是从上往下打印的也就是说,先进的就会在下面
temp.pop();
cout<<"("<<p2.first<<","<<p2.second<<")"<<endl;
stk.push(p2);
}
return;
}
for(int i = 0;i < 4;i++){
int ix = x + index[i][0];
int iy = y + index[i][1];
if(ix >= 0&&ix != rows&&iy >=0&&iy != cols&&mark[ix][iy] == false&&map[ix][iy] == 0){
mark[ix][iy] = true;
stk.push(make_pair(ix,iy));
dfs(ix,iy);
mark[ix][iy] = false;
stk.pop();
}
}
}
int main(){
dfs(0,0);
cout<<"completed"<<endl;
stack<int> a;
for(int i =0;i<10;i++){
a.push(i);
}
while(!a.empty()){
cout<<a.top()<<endl;
a.pop();
}
}
以上过程中dfs后有一个回溯的过程:stk.pop();是因为等遇到错的路径的时候要回到根路径
6、快速排序(双路快排)
void quicksort(int a[],int l,int r){
int temp = a[l];
int i = l,j = r;
if(l > r){
return;
}
while(i!=j){
while(i<j&&a[j] >= temp)//这里右边的一定要在前
j--;
while(i < j&&a[i] <= temp)
i++;
if(i < j){
swap(a[i],a[j]);
}
}
swap(a[l],a[i]);
quicksort(a,l,i-1);
quicksort(a,i+1,r);
}
int main()
{
int n =10;
int arr[10] = {2,1,4,5,1,2,5,8,10,11};
quicksort(arr,0,n-1);
for(int i = 0;i < n;i++){
cout<<arr[i]<<endl;
}
}
7、堆排序
void shiftdown(int arr[],int n,int k){
while(2*k+1 < n){
int j = 2*k +1;
if(j + 1 < n &&arr[j + 1] > arr[j])
//最小堆的话就是if(j + 1 < n &&arr[j + 1] < arr[j])
j = j + 1;
if(arr[k] > arr[j])
//if(arr[k] < arr[j])
break;
swap(arr[k],arr[j]);
k = j;
}
}
void heapsort(int arr[],int n){
//heapfiy process
for(int i = n/2;i >= 0;i--)
shiftdown(arr,n,i);
for(int i = n -1;i > 0;i--){
swap(arr[0],arr[i]);
shiftdown(arr,i,0);
}
}
using namespace std;
typedef struct node
{
int value;
DNode* Dleft;
DNode* Dright;
} DNode;
DNode* head = NULL;
DNode* createDL(int value){
DNode* head = (DNode*)malloc(sizeof(DNode));
head->value = value;
head->Dleft = head->Dright = head;
}
DNode* insert(int index,int val){
if(index == 0){
DNode* tempnode = (DNode*)malloc(sizeof(DNode));
if(!tempnode)
return -1;
tempnode->Dleft = head;
tempnode->Dright = head->Dright;
head->Dright->Dleft = tempnode;
head->Dleft = tempnode;
}
int i = 0;
DNode *pnode = head;
while(i < index){
pnode = pnode->Dleft;
i++;
}
DNode* newnode = (DNode*)malloc(sizeof(DNode));
newnode->Dleft = pnode->Dleft;
newnode->Dright = pnode;
pnode->Dleft->Dright = newnode;
pnode->Dleft = newnode;A
}