【算法分析复习】第4章

1. 减治法

减治技术利用了一个问题给定实例的解和同样问题较小实例的解之间的某种关系。一旦建立了这种关系,我们既可以从顶至下(递归地),也可以从底至上(非递归地)地来运用该关系。
减治法有3种主要的变种:

  • 减去一个常量;
  • 减去一个常量因子;
  • 减去的规模是可变的。

2. 插入排序

  • 有3种合理的做法可以达到这个目的,它们各不相同。
  • 第一,我们可以从左到右扫描这个有序的子数组,直到遇到第一个大于等于A[n-1]的元素,然后就把A[n-1]插在该元素的前面。
  • 第二,我们可以从右到左扫描这个有序的子数组,直到遇到第一个小于等于A[n-1]的元素,然后就把A[n-1]插在该元素的后面。
  • 第三种做法是使用折半查找为A[n-1]在有序子数组中找到一个合适的位置。这种算法被称为折半插入排序。
  • 虽然插入排序很明显是基于递归思想的,但从底至上地实现这个算法,效率会更高,也就是使用迭代。就像图5.3所显示的,从A[1]开始,到A[n-1]为止,A[i]被插在数组的前个有序元素中的适当位置上(但是,和选择排序不同,这个位置一般来说并不是它们的最终位置)。
算法 InsertionSort(A[0..n-1])
	 //用插入排序对给定数组排序
	 //输入:n个可排序元素构成的一个数组A[0..n-1] 
	 //输出:非降序排列的数组A[0..n-1]
	  for i=1 to n-1 do
            v=A[i]
            j=i-1
	      while j>=0 and A[j] >v do
                A[j+1]=A[j]
                j=j-1	
           A[j+1]=v

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int a[100],n;
void swap(int &a,int &b){
    int temp=a;
    a=b;
    b=temp;
}

void insertSort(){
    for(int i=1;i<n;i++){
        for(int j=i-1;j>=0&&a[j+1]<a[j];j--){
            swap(a[j+1],a[j]);
        }
    }
}

int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    insertSort();
    for(int i=0;i<n;i++){
        cout<<a[i]<<" ";
    }
    return 0;
}

3. 俄式乘法

  • 现在我们来考虑对两个正整数相乘的非主流算法,它被称为俄式乘法,或者俄国农夫法。
  • 假设n和m是两个正整数,我们要计算它们的乘积,同时,我们用n的值作为实例规模的量度。
  • 当n为偶数时:n * m=n/2 * 2m
  • 当n为奇数时:n * m=(n-1)/2 * 2m + m
  • 并以1*m=m作为结束条件。
#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int mul(int m, int n){
    int sum=0,a=0;
    if(n==0||m==0)
        return 0;
    if(n==1)
        return m;
    while(n!=1){
        if(n%2==0){
            n/=2;//n>>=1;
            m*=2;//m<<=1;
        }else{
            n/=2;//向下取整n=(n-1)/2;
            a+=m;
            m*=2;
        }
    }
    sum=a+m;
    return sum;
}


int main(){
    int m,n,sum;
    cin>>m>>n;
    sum=mul(m,n);
    cout<<sum;
    return 0;
}

4. 二叉树查找和插入

参考博客

  • 二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
  • 二叉排序树的查找过程和次优二叉树类似,通常采取二叉链表作为二叉排序树的存储结构。中序遍历二叉排序树可得到一个关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索,插入,删除的复杂度等于树高,O(log(n)).
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
struct BTNode {
    int data;
    BTNode *lchild,*rchild;
};
class BTree {
private:
    BTNode *root;                    //二叉搜索树的根结点
    void creat(int loc, BTNode *p); //创建二叉搜索树,递归形式创建,私有函数
    void travel(BTNode *p);            //用来遍历(中序),输出时候需要调用的
    int *data, number;                //这个是用来存储输入的数组,估计不需要了,下一个版本会删除
    void search(int key, BTNode *p, bool &flag);    //查找,其实这个查找方法和二分法类似
    void insert(BTNode *p, int x);        //插入函数
public:
    BTree(int a[], int n);
    void Creat();
    void Insert(int x);
    void Search(int key);
    void Print();
};
void BTree::creat(int loc, BTNode * p)
{
    if (data[loc] > p->data)    //判断要输入的值是比结点值大还是小,大向右,小向左
    {
        if (p->rchild == NULL)//然后再判断,如果比结点值大且右孩子为空就创建
        {
            p->rchild = new BTNode();
            p->rchild->data = data[loc];
            p->rchild->lchild = p->rchild->rchild = NULL;
        }
        else                  //不为空就继续进行判断比较,递归
        {
            creat(loc, p->rchild);
        }
    }
    else if (data[loc] < p->data)//同理
    {
        if (p->lchild == NULL)
        {
            p->lchild = new BTNode();
            p->lchild->data = data[loc];
            p->lchild->lchild = p->lchild->rchild = NULL;
        }
        else
        {
            creat(loc, p->lchild);
        }

    }
}
void BTree::travel(BTNode * p)
{
    //中序遍历,左根右
    if (p != NULL)
    {
        travel(p->lchild);//先左
        cout << p->data << " ";//根
        travel(p->rchild);//后右
    }
}
void BTree::search(int key, BTNode *p, bool &flag)
{
    while (p)
    {
        if (p->data == key)        //找到
        {
            flag = true;
            break;
        }
        else if (p->data > key)    //比结点的值小就向左找
        {
            p = p->lchild;
        }
        else                    //比结点的值小就向左找
        {
            p = p->rchild;
        }
    }

}
void BTree::insert(BTNode *p, int x)
{
    if (x > p->data)
    {
        if (p->rchild == NULL)
        {
            p->rchild = new BTNode();
            p->rchild->data = x;
            p->rchild->rchild = p->rchild->lchild = NULL;
            cout << p->rchild->data << "插入成功!" << endl;
        }
        else
            insert(p->rchild, x);
    }
    else if (x < p->data)
    {
        if (p->lchild == NULL)
        {
            p->lchild = new BTNode();
            p->lchild->data = x;
            p->lchild->rchild = p->lchild->lchild = NULL;
            cout << p->lchild->data << "插入成功!" << endl;
        }
        else
            insert(p->lchild, x);
    }
    else
    {
        cout << "不可以插入已经存在于二叉搜索树中的元素!" << endl;
    }


}
BTree::BTree(int a[], int n)
{
    int mid = a[0];        //把第一个数据作为二叉树的根结点的数值
    root = new BTNode();
    root->data = mid;
    root->lchild = root->rchild = NULL;
    number = n;
    data = new int[number];
    for (int i = 0; i < number; i++)
    {
        data[i] = a[i];        //创建这个数组个人觉得有点多余,其实可以直接在构造函数里完成
                            //自己改一下吧,直接在构造函数里调用creat,参数需要调整一下
    }
}
void BTree::Insert(int x)
{
    BTNode *p = root;
    insert(p, x);
    //这里可以把insert函数增加一个参数bool类型来判断是否真的是插入成功了
    //插入成功会有提示,失败不会打印插入成功的消息
}
void BTree::Search(int key)
{
    //此函数对应私有函数没有返回值,可以自己更改,把地址取出来(目前没有用所以我只是做了一个简单的判断)
    BTNode *p = root;
    bool flag = false;
    search(key, p, flag);
    if (flag)
    {
        cout << "搜索到" << key << "在二叉树中" << endl;
    }
    else
    {
        cout << "未查找到指定数据!" << endl;
    }
}
void BTree::Print()
{
    BTNode *p = root;
    travel(p);
    cout << endl;

}
void BTree::Creat()
{
        BTNode *p = root;
        for (int i = 1; i < number; i++)    //从1开始是因为root在构造函数中已经被赋值了
        {
            creat(i, p);
        }
        cout << "二叉搜索树创建成功了。。。吧" << endl;
}

int main()
{
    cout << "请输入二叉搜索树的元素个数:";
    int number, *a, key, x;
    cin >> number;
    a = new int[number];
    cout << "请分别为这些元素赋值:" << endl;
    for (int i = 0; i < number; i++)
    {
        cin >> a[i];
    }
    BTree test(a, number);
    test.Creat();
    test.Print();
    cout << "请输入要查找的数值" << endl;
    cin >> key;
    test.Search(key);
    cout << "请输入要插入的数值" << endl;
    cin >> x;
    test.Insert(x);
    test.Print();
    system("pause");
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值