数据结构基础笔记002 算法形式规范【未完】

2017-07-17  本文已影响0人  Cytosine

《数据结构基础》
作者: [美]Ellis Horowitz 霍罗维兹
译者: 朱仲涛
出版社: 清华大学出版社
ISBN: 9787302186960
豆瓣读书 中查看本书

算法综论

  1. 输入:从外界获取零个或多个量
  2. 输出:产生至少一个量
  3. 确定性:每条指令清晰、无二义性
  4. 有限性:算法对所有情形都能在执行有限步之后结束。
  5. 有效性:每条指令都是基本可执行的。

查找策略:折半查找

分析

假定n≥1个有序整数存储在数组list之中,list[0]≤list[1]≤...≤...≤list[n-1]。我们想知道整数 searchnum是否出现在这个表中,如果是,则返回下标indexsearchnum=list[index];否则返回-1。由于这个表有序,可以用以下方法查找给定点值:
leftright分别表示表中待查范围的左右端点,初值为:

left=0;
right=n-1;

middle为表中点下标值:

middle=(left+right)/2;

searchnumlist[middle]比较的结果,有三种可能:

  1. searchnum < list[middle]:如果searchnum在表中,它一定在位置0middle-1之间。所以:
right=middle-1;
  1. searchnum == list[middle]:返回middle
  2. searchnum > list[middle]:如果searchnum在表中,它一定在位置middle+1n-1之间。所以:
left=middle+1;

searchnum还没找到,同时尚有没检查的其他整数,则重新计算middle,重复查找过程。
确定不再有待查找的数据leftright是全表的两个端点,查找在两者之间进行,一旦left大于right,则说明再也没有待查找的数据了。

代码实现

迭代实现

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 8

int binsearch(int list[],int searchnum,int left,int right);//定义折半查找函数原型

int main(){
    int list[N];

    //随机生成N个整数
    srand((unsigned)time(NULL));
    for(int i=0;i<N;i++){
        list[i]=rand()%100;
    }

    //打印初始化结果
    printf("初始化list:\n");
    for(int i=0;i<N;i++){
        printf("[%d]%d\t",i,list[i]);
    }
    printf("\n");

    //使用简单的冒泡排序将list从小到大排序
    for(int i=0;i<N;i++){
        for(int j=i;j<N;j++){
            if(list[i]>list[j]){
                int t=list[i];
                list[i]=list[j];
                list[j]=t;
            }
        }
    }

    //打印排序结果
    printf("list排序后:\n");
    for(int i=0;i<N;i++){
        printf("[%d]%d\t",i,list[i]);
    }
    printf("\n");

    //获取用户输入,用户需输入欲查找的数字
    int searchnum;
    printf("请输入欲查找的整数。若整数存在,程序将返回整数的下标;若不存在,返回-1:\n");
    scanf("%d",&searchnum);

    //调用折半查找函数
    int result=binsearch(list,searchnum,0,N-1);

    //输出结果
    printf("查找结果\n%d",result);

    return 0;
}

int binsearch(int list[],int searchnum,int left,int right){
    int middle,temp;
    while(left<=right){
        middle=(left+right)/2;

        //判断searchnum与list[middle]相比的大小关系
        //searchnum == list[middle]    temp=0
        //searchnum >  list[middle]    temp=1
        //searchnum <  list[middle]    temp=-1
        temp=(searchnum==list[middle])?0:(searchnum>list[middle])?1:-1;

        //根据 searchnum与list[middle]相比的大小关系 调整left right的值
        switch(temp){
            case 0:return middle;
            case 1:left=middle+1;break;
            case -1:right=middle-1;break;
        }

    }
    return -1;
}

2. 递归实现:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 8

int binsearch(int list[],int searchnum,int left,int right);//定义折半查找函数原型

int main(){
    int list[N];

    //随机生成N个整数
    srand((unsigned)time(NULL));
    for(int i=0;i<N;i++){
        list[i]=rand()%100;
    }

    //打印初始化结果
    printf("初始化list:\n");
    for(int i=0;i<N;i++){
        printf("[%d]%d\t",i,list[i]);
    }
    printf("\n");


    //使用简单的冒泡排序将list从小到大排序
    for(int i=0;i<N;i++){
        for(int j=i;j<N;j++){
            if(list[i]>list[j]){
                int t=list[i];
                list[i]=list[j];
                list[j]=t;
            }
        }
    }

    //打印排序结果
    printf("list排序后:\n");
    for(int i=0;i<N;i++){
        printf("[%d]%d\t",i,list[i]);
    }
    printf("\n");

    //获取用户输入,用户需输入欲查找的数字
    int searchnum;
    printf("请输入欲查找的整数。若整数存在,程序将返回整数的下标;若不存在,返回-1:\n");
    scanf("%d",&searchnum);

    //调用折半查找函数
    int result=binsearch(list,searchnum,0,N-1);

    //输出结果
    printf("查找结果\n%d",result);

    return 0;
}

int binsearch(int list[],int searchnum,int left,int right){
    int middle,temp;
    if(left<=right){
        middle=(left+right)/2;

        //判断searchnum与list[middle]相比的大小关系
        //searchnum == list[middle]    temp=0
        //searchnum >  list[middle]    temp=1
        //searchnum <  list[middle]    temp=-1
        temp=(searchnum==list[middle])?0:(searchnum>list[middle])?1:-1;

        //根据 searchnum与list[middle]相比的大小关系 调整left right的值
        switch(temp){
            case 0:return middle;
            case 1:return binsearch(list,searchnum,middle+1,right);
            case -1:return binsearch(list,searchnum,left,middle-1);
        }

    }
    return -1;
}

递归

递归实现置换

问题描述

给定n≥1个元素的集合,打印这个集合所有可能的置换。
例如,给定集合{a,b,c},它的所有置换是{(a,b,c),(a,c,b),(b,a,c),(b,c,a),(c,a,b),(c,b,a)}。

问题分析

容易看出,给定n个元素,共有n!种置换。 我们通过观察集合{a,b,c,d},得到生成所有置换的简单算法,以下是算法的构造过程:

  1. a跟在(b,c,d)的所有置换之后。
  2. b跟在(a,c,d)的所有置换之后。
  3. c跟在(a,b,d)的所有置换之后。
  4. d跟在(a,b,c)的所有置换之后。

“跟在所有……置换之后”是构建递归算法的关键,这句话启发我们,如果解决了n-1个元素的置换问题,则n个元素的置换问题就可以解决了。

代码实现

注意

代码
(书P13,尚有错误)

#include <stdio.h>
#define SWAP(x,y,t)( (t)=(x),(x)=(y),(y)=(t) )

void perm(char *list,int i,int n);

int main(){
    char * list="abcd";
    perm(list,0,3);

    return 0;
}

void perm(char *list,int i,int n){
    int temp;
    if(i==n){
        for(int j=0;j<=n;j++){
            printf("%c",list[j]);
        }
        printf("\n");
    }else{
        for(int j=i;j<=n;j++){
            SWAP(list[i],list[j],temp);
            perm(list,i+1,n);
            SWAP(list[i],list[j],temp);
        }
    }
}

上一篇下一篇

猜你喜欢

热点阅读