基本算法之减治法

插入排序

思路:在此是将数组进行升序排序,把长度为n的数组看做有序的a[0.......n-2]和a[n-1]两部分组成,然后从右到左扫描a[0......n-2]数组,找到第一个小于或等于a[n-1]的元素,然后将a[n-1]插入到,然后把a[n-1]插入到该元素的后面,体现了分治的思想。  该算法最坏情况是一个降序排列的输入,需要经过n*n次比较,最好的情况是一个升序排列的输入,需要比较的次数为n-1次,平均效率也要比冒泡排序和选择排序要好。


#include "stdafx.h"
#include<iostream>
using namespace std;

void InsertSort(int *a,int n)    {
    
    int temp;
    int j;
    for(int i=1;i<n;++i)    {
        temp=a[i];
        j=i-1;
        while(j>=0&&a[j]>temp)    {
            a[j+1]=a[j];
            j=j-1;
        }
        a[j+1]=temp;
    }

}

// 函数模板

template<typename T>

void InsertSort(T *arr,const int &n)    // arr为存放数据,n 为长度
{
if(0==n||1==n)
return;
for(int i=1;i!=n;++i) {

T curValue=arr[i];
int back=i-1;
while(back>=0&&arr[back]>curValue) {
    arr[back+1]=arr[back];
--back;
}
arr[back+1]=curValue;
}
}




int _tmain(int argc, _TCHAR* argv[])
{
    
    int num,a[20];
    cout<<"输入数据的个数:"<<endl;
    cin>>num;
    cout<<"依次输入每个数:"<<endl;
    for(int i=0;i<num;++i)    {
        cin>>a[i];
    }
    InsertSort(a,num);
    for(int i=0;i<num;++i) {
        cout<<a[i]<<"   ";
    }
    system("pause");
    return 0;
}





无向图的深度优先遍历

思路:全局数组visited[] 用来跟踪那些点已经被遍历,算法的效率与用来表示图的数据结构规模成正比,对于邻接矩阵表示法,该遍历的效率为n*n;对于邻接表表示法,效率为(n+e),其中n和e 分别指图的顶点数和边数。深度优先遍历基本应用包括检查图的连通性和无环性等。。

#include "stdafx.h"
#include<iostream>
using namespace std;
#define MAXNUM 30
typedef char vertextype;
typedef int edgetype;
typedef struct Graph{
    vertextype vertex[MAXNUM];
    edgetype edge[MAXNUM][MAXNUM];
    
    int vernumber;
    int edgenumber;

};

int visited[MAXNUM];
int CreateGraph(Graph &gra){
    cout<<"输入的顶点的个数和边的条数:"<<endl;
    
    cin>>gra.vernumber>>gra.edgenumber;
    cout<<"输入顶点的值"<<endl;
    for(int i=0;i<gra.vernumber;++i)
        cin>>gra.vertex[i];

    for(int i=0;i<gra.vernumber;++i)
        for(int j=0;j<gra.vernumber;++j)    {
            gra.edge[i][j]=0;
        }
    cout<<"输入每一条边,对每一个顶点从0开始依次编号0 1 2...."<<endl;
    for(int i=0;i<gra.edgenumber;++i)    {
        int temp1,temp2;
        cin>>temp1>>temp2;
        gra.edge[temp1][temp2]=1;
        gra.edge[temp2][temp1]=1;

    }
    return 1;

}

void DFS(Graph gra,int k)    {
    
    cout<<gra.vertex[k]<<"---->";
    visited[k]=1;
    for(int i=0;i<gra.vernumber;++i)    {
        if(gra.edge[k][i]=1&&visited[i]!=1)
          DFS(gra,i);
    
    }
}

void DFSTraverse(Graph gra,int k)    {

    for(int i=0;i<gra.vernumber;++i)
        visited[i]=0;

    DFS(gra,k);

    for(int i=0;i<gra.vernumber;++i)
        if(visited[i]==0)
            DFS(gra,i);

}


int _tmain(int argc, _TCHAR* argv[])
{
    
   
    Graph gra;
    CreateGraph(gra);
    DFSTraverse(gra,0);
    system("pause");

return 0;

}

无向图的广度优先遍历

思路:与深度优先遍历类似,效率情况也是一样的,不同之处是深度优先是递归调用,应用数据结构”栈“,而广度优先应用了队列 。

#include "stdafx.h"
#include<iostream>
using namespace std;
#define MAXNUM 30
typedef char vertextype;
typedef int edgetype;
typedef struct Graph{
    vertextype vertex[MAXNUM];
    edgetype edge[MAXNUM][MAXNUM];
    
    int vernumber;
    int edgenumber;

};


typedef struct QueueNode{
    int vertex;
    QueueNode *next;

};

typedef struct Queue{
    QueueNode *front;
    QueueNode *rear;
};


void InitQueue(Queue &que){
    
    que.front=que.rear=NULL;

}

bool IsEmpty(Queue que) {
    if(que.front==NULL&&que.rear==NULL)
        return true;
    else
        return false;
}


void InsertQueue(Queue &que,int vex){
    
    
    QueueNode*node=(QueueNode *)malloc(sizeof(QueueNode));
    node->vertex=vex;
    node->next=NULL;

    if(IsEmpty(que))    {
    
        que.front=que.rear=node;
    }
    else    {
        que.rear->next=node;
        que.rear=node;
    
    
    }



}



int DeleteQueue(Queue &que)    {
    QueueNode *temp;
    int  vex;
    if(que.rear==que.front==NULL) {
        cout<<"队列空了"<<endl;
        
    }

    temp=que.front;
    vex=temp->vertex;
    que.front=que.front->next;

    if(que.rear==temp)    {
    
        que.rear=NULL;
    }
    free(temp);
    return vex;

    }







int visited[MAXNUM];
int CreateGraph(Graph &gra){
    cout<<"输入的顶点的个数和边的条数:"<<endl;
    
    cin>>gra.vernumber>>gra.edgenumber;
    cout<<"输入顶点的值"<<endl;
    for(int i=0;i<gra.vernumber;++i)
        cin>>gra.vertex[i];

    for(int i=0;i<gra.vernumber;++i)
        for(int j=0;j<gra.vernumber;++j)    {
            gra.edge[i][j]=0;
        }
    cout<<"输入每一条边,对每一个顶点从0开始依次编号0 1 2...."<<endl;
    for(int i=0;i<gra.edgenumber;++i)    {
        int temp1,temp2;
        cin>>temp1>>temp2;
        gra.edge[temp1][temp2]=1;
        gra.edge[temp2][temp1]=1;

    }
    return 1;

}





void BFSTraverse(Graph gra,int k){

    Queue que;
    InitQueue(que);
    
    for(int i=0;i<gra.vernumber;++i)
        visited[i]=0;

    cout<<gra.vertex[k]<<"--->";

    visited[k]=1;

    InsertQueue(que,k);

    while(!IsEmpty(que))    {
        int current;
        current=DeleteQueue(que);
        for(int i=0;i<gra.vernumber;++i)    {
        
            if(gra.edge[current][i]&&visited[i]==0)    {
                cout<<gra.vertex[i]<<"--->";
                visited[i]=1;

                InsertQueue(que,i);
            }
        }
    }
}




int _tmain(int argc, _TCHAR* argv[])
{
    


    Graph gra;
    CreateGraph(gra);
    BFSTraverse(gra,0);
    system("pause");

     return 0;
}


拓扑排序

思路:  找出入度为0的顶点,将其如栈,循环出栈,将其删除(输出),然后将与该点相连的其他的点的入度减一(减治思想),如果减一后入度为0则将其入栈,然后再循环。 当最后栈为空,而输出的点少于有向图中的顶点数时,说明存在环。具体代码如下:

#include "stdafx.h"
#include<iostream>
#include<stack>
using namespace std;

#define MAX 30

typedef struct node{
    int vertex;
    struct node *next;
};

typedef node nodearray[MAX];

typedef struct Graph{
    int vexnum;
    int edgenum;
    
    nodearray edge;
    int indegree[MAX];

};

int CreateDirGraph(Graph &gra) {
    cout<<"输入顶点的个数和边的数量"<<endl;
    int vexnum,edgenum;

    cin>>vexnum>>edgenum;
    gra.vexnum=vexnum;
    gra.edgenum=edgenum;
    for(int i=0;i<vexnum;++i)    {
        gra.edge[i].vertex=i;
        gra.edge[i].next=NULL;
        gra.indegree[i]=0;

    }
    cout<<"依次输入每一条边:"<<endl;
    for(int i=0;i<edgenum;++i)    {
    
        int temp1,temp2;
        cin>>temp1>>temp2;
        node * newnode=NULL;
        newnode=(node*)malloc(sizeof(node));
        newnode->vertex=temp2;
        newnode->next=gra.edge[temp1].next;
        gra.edge[temp1].next=newnode;
        gra.indegree[temp2]++;
    
    }
    return 1;

}


//  拓扑排序的源删除算法
void TopologicSort(Graph gra)    {

    
    stack<int> topstack;
    int count=0;
    int current;
    node * thenext=NULL;
    for(int i=0;i<gra.vexnum;++i)    {
    
        if(gra.indegree[i]==0)
            topstack.push(i);
    }

    while(topstack.size()!=0)    {
    
        current=topstack.top();
        topstack.pop();
        cout<<"  "<<current;
        count++;
        for(thenext=gra.edge[current].next;thenext!=NULL;thenext=thenext->next)    {
        
            int k=thenext->vertex;
            gra.indegree[k]--;

            if(gra.indegree[k]==0)
                topstack.push(k);
        }
    }
    cout<<endl;
    if(count<gra.vexnum)
        cout<<"有回路"<<endl;
}


int _tmain(int argc, _TCHAR* argv[])
{
    
    Graph gra;

    CreateDirGraph(gra);

    TopologicSort(gra);

    system("pause");
    
    
    return 0;
}


生成排列 最小变化要求

Johnson-Trotter 算法

生成子集算法

格雷码


减治之减常因子算法

假币问题

俄式乘法

约瑟夫斯问题

迭代是反复、 循环执行的意思,根据迭代关系不断更新迭代变量,朝着迭代算法的结束条件循环执行。

递归算法就包含有迭代的意思,不断执行某一个操作,不断更新规模,朝着递归出口不断执行。

二叉查找树的查找和插入

拈游戏

平衡查找树(AVL)

2-3树

快速傅立叶变换


   


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值