数据结构4——查找

------------恢复内容开始------------

栈:后进先出

struct Stack{
 ElemType data[MaxSize];
 int top;
};
 
1-1栈的基本操作

以下是利用栈判断回文序列

boolsymmetry(inta[],intl){inti,e;Stack*s;InitStack(s);for(i=0;i<l;i++){Push(s,a[i]);}for(i=0;i<l;i++){Pop(s,e);if(a[i]!=e){DestroyStack(s);returnfalse;}}DestroyStack(s);returntrue;}intmain(){inta[]={1,2,3,2,1};cout<<symmetry(a,5);}
1-2回文

我们也可以利用链式存储完成栈的构建

#include <iostream>
#include <stdlib.h>
using namespace std;


struct Stack//Struct Link
{
    int data;
    Stack *next;
};


void InitStack(Stack *&s)
{
    s = NULL;
}


void DestroyStack(Stack *&s)
{
    if(s==NULL){
        return;
    }
    Stack *p=s,*q=s->next;
    while(q){
        free(p);
        p=q;
        q=q->next;
    }
    free(p);
}


bool StackEmpty(Stack *s)
{
    return(s==NULL);
}//判断栈是否为空
 

void Push(Stack *&s,int e)//这里不是bool是因为链式存储一般不需要考虑栈满的情况 
{
    if(s==NULL){
        s=new Stack;
        s->next=NULL;
        s->data=e;
        return;
    }
    Stack *p=s;
    for(;p->next;p=p->next);
    p->next=new Stack;
    p=p->next;
    p->data=e;
    p->next=NULL;
}//栈的操作只操作最后放入的元素,如果将后来的元素放在队尾部,会给后续操作带来不便
//如果只需要进行栈操作的话,入栈建议将数据放在头部 
void Push2(Stack *&s,int e)
{
    if(s==NULL){
        s=new Stack;
        s->next=NULL;
        s->data=e;
        return;
    }
    Stack *p=new Stack;
    p->next=s;
    p->data=e;
    s=p;
}


bool Pop(Stack *&s,int &e)
{
    if(s==NULL)return false;
    e=s->data;
    Stack *p=s;
    s=s->next;
    free(p);
    return true;
}


bool GetTop(Stack *&s,int &e)
{
    if(s==NULL)return false;
    e=s->data;
    return true;
}
2链栈

队列:先进先出

 

 (来源:mooc——数据结构——武汉大学)

队列需要有队首和队尾两个指针,其它基本操作的实现都可参考栈

将基础操作的rear++和front++改为

rear=(rear+1)%MaxSize和front=(front+1)%MaxSize
并约定rear=front为队空(初始)条件
(rear+1)%MaxSize=front为队满条件
 
 
 
对于环形队列来说,如果知道队头指针和队列中元素个数,则可以计算出队尾指针。也就是说,可以用队列中元素个数代替队尾指针。
 
#include <stdlib.h>
struct Queue
{
    int data[5];
    int front;
    int len;
};


void InitStack(Queue *&s)
{
    s=new Queue;
    s->front=0;
    s->len=0;
}


void DestroyStack(Queue *&s)
{
    free(s);
}


bool StackEmpty(Queue *s)
{
    return(s->len==0);
}
 

bool enQueue(Queue *&s,int e)
{
    if(len==5)return false;
    s->data[(s->front+s->len)%5]=e;
    len++;
    return true;
}


bool deQueue(Stack *&s,int &e)
{
    if(len==0)return false;
    e=s->data[s->front];
    s->front=(s->front+1)%5;
    return true;
}
3环形队列(用长度代替队尾指针)

 

 

------------恢复内容开始------------

一、线性表的查找

  顺序查找:ASL成功=(n+1)/2  ASL不成功=n

  二分查找:成功时最多的关键字比较次数为[log2(n+1)] 不成功时关键字比较次数为[log2(n+1)]

       ASL成功=(n+1)/n*log2(n+1)-1≈log2{n+1)-1

  分块查找:介于顺序查找和二分查找之间

二、二叉排序树

   

//二叉排序树 
typedef struct node
{
    int key;
    int data;
    struct node *lchild,*rchild;    
}BSTNode;


BSTNode *SearchBST(BSTNode*bt,int k)
{
    if(bt==NULL||bt->key==k)return bt;
    if(k<bt->key)return SearchBST(bt->lchild,k);
    else return SearchBST(bt->rchild,k);
}
二叉排序树查找
int InsertBST(BSTNode *&p,int k)//利用的是先序遍历的思想 
{
    if(p==NULL)
    {
        p=new BSTNode;
        p->key=k;p->lchild=NULL;p->rchild=NULL;
        return 1;    
    }
    else if(k==p->key)return 0;//存在相同关键字的节点返回0
    else if(k<p->key)return InsertBST(p->lchild,k);
    else return InsertBST(p->rchild,k); 
} 
二叉排序树插入

可以看出二叉排序树应用了顺序遍历的思想

// 二叉排序树的删除
//查找被删除节点 
int deletek(BSTNode *&bt,int k)
{
    if(bt==NULL)return 0;
    if(k==bt->key)
    {
        deletep(bt);
        return 1;
    }
    else if(k<bt->key)deletek(bt->lchild,k);
    else deletek(bt->rchild,k);
}
//删除节点
void deletep(BSTNode *&p)
{
    BSTNode *q;
    if(p->rchild==NULL)
    {
        q=p;p=p->lchild;
        free(q);
    }
    else if(p->lchild==NULL)
    {
        q=p;p=p->rchild;
        free(p);
    }
    else//左右子树都存在的情况 
    { 
        for(q=p->lchild;q->rchild;q=q->rchild);//q指向p左子树最右下节点
        p->key=q->key;p->data=q->data;//将要删除的节点替换为最右下的节点 
        BSTNode *temp=q;q=q->lchild;free(temp);//将原来最右下的节点删除 
    }
}
    
二叉排序树删除

平衡二叉树(AVL):一颗二叉树中每个节点的左右子树的高度至多相差1

三、哈希查找

解决冲突的方法:

  开放定址法->线性探查法(堆积现象)、平方探查法(无法探查到哈希表上的全部单元)

数组形式:

#include <math.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
int jp(int m)//判断是否为素数,否则返回0,是则返回最大因数 
{
    for(int i=floor(sqrt((double)m));i<floor(m/2);i++)
    {
        if(m%i==0)return m/i;
    }
    return 0;
}
int maxp(int m){
    int i=m;
    for(;jp(i);i--);
    return i+1;
}
//生成哈希表

//常见的hash函数(除留余数法)
int hash(int key,int l)//l为hash表长度 
{    
    return key%maxp(l);
}
最简单的哈希函数
class hashlist
{
    protected:
        int * ListHead;
        int Lenth;
    public:
        hashlist(int l)
        {
            ListHead=(int*)malloc(l*sizeof(int));
            Lenth=l;
            for(int i=0;i<Lenth;i++){
                ListHead[i]=0;
            }
        }
        void create(int *keys)
        {
            int k,h,flag;
            for(int i=0;k=keys[i];i++)
            {
                for(h=hash(k,Lenth);ListHead[h%Lenth];h++)//线性探查法解决冲突 
                {
                    if(ListHead[h%Lenth]==k)
                    {
                        cout<<"this key has already been put in:"<<k<<endl;
                        break;
                    }
                    if(h-h%Lenth>=Lenth)
                    {
                        cout<<"this hashlist is full"<<endl;
                        return;
                    }
                    
                };
                
                ListHead[h%Lenth]=k;
            }
            cout<<"hashlist created"<<endl;
        }
        void show(){
            cout<<Lenth<<endl;
            for(int i=i;i<Lenth;i++){
                cout<<i<<":"<<ListHead[i]<<"\t";
            }
            cout<<endl;
        }
        int search(int key)
        {
            int h=hash(key,Lenth),k;
            for(;ListHead[h%Lenth];h++)
            {
                if(ListHead[h%Lenth]==key)return h%Lenth;
                if(h-h%Lenth==Lenth)return 0;
            }
            return 0;
        }
        
};
哈希表的建立和查找
int main()
{
    int a[]={1,2,3,3,4,5,0};
    hashlist hash1(15);
    hash1.create(a);
    hash1.show();
    cout<<hash1.search(4);
}
使用实例

运行结果:

this key has already been put in:3
hashlist created
0:0     1:1     2:2     3:3     4:4     5:5     6:0     7:0     8:0     9:0     10:0    11:0    12:0    13:0    14:0   
4

  拉链法:

//拉链法
d=hash(k);
p=ha[d];
while(p!=NULL&&p->key!=k)p=p->next;
if(p==NULL)return 0;//查找失败
else return p;//返回查找值所在节点 
拉链法中的查找

 

posted on 2020-05-31 14:06  crazyplayer  阅读(125)  评论(0编辑  收藏  举报

导航