算法导论_第十章_基本数据结构

12 篇文章 0 订阅
10 篇文章 0 订阅


算法导论_第十章_基本数据结构

队列和栈:


队列为先进先出,栈为先进后出。


其可以用数组和链表实现。



队列代码如下

/*************************************************************************
	> File Name: queue.cpp
	> Author:chudongfang 
	> Mail:1149669942@qq.com 
	> Created Time: 2016年06月30日 星期四 10时39分08秒
 ************************************************************************/

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include <algorithm>
#define INF 0x3f3f3f3f
#define LEN 5
using namespace std;
typedef long long ll;

int dequeue();
int enqueue(int x);
bool queue_empty();
bool queue_full();

int queue[LEN+1];
int head=1,tail=1;
int main(int argc,char *argv[])
{
    enqueue(1);
    for(int i=1;i<=LEN;i++)  printf("%d ",queue[i]);
    printf("\nhead=%d\ntail=%d\n\n",head,tail);
    
    enqueue(2);
    for(int i=1;i<=LEN;i++)  printf("%d ",queue[i]);
    printf("\nhead=%d\ntail=%d\n\n",head,tail);
    
    enqueue(3);
    for(int i=1;i<=LEN;i++)  printf("%d ",queue[i]);
    printf("\nhead=%d\ntail=%d\n\n",head,tail);
    
    printf("%d\n",dequeue());
    for(int i=1;i<=LEN;i++)  printf("%d ",queue[i]);
    printf("\nhead=%d\ntail=%d\n\n",head,tail);
    
    enqueue(1);
    for(int i=1;i<=LEN;i++)  printf("%d ",queue[i]);
    printf("\nhead=%d\ntail=%d\n\n",head,tail);
    
    enqueue(2);
    for(int i=1;i<=LEN;i++)  printf("%d ",queue[i]);
    printf("\nhead=%d\ntail=%d\n\n",head,tail);
    
    enqueue(3);
    for(int i=1;i<=LEN;i++)  printf("%d ",queue[i]);
    printf("\nhead=%d\ntail=%d\n\n",head,tail);
    

    return 0;
}

int enqueue(int x)//入队
{
    if(queue_full()) 
    {
        printf("the queue is full!\n");
        return 0;
    }
    queue[tail]=x;
    if(tail==LEN)  
        tail=1;
    else 
        tail++;
}


int dequeue()//出队
{
    if(queue_empty())
    {
        printf("the queue is empty!");
        return 0;
    }

    int x=queue[head];
    if(head==LEN) 
        head=1;
    else 
        head++;
    return x;
}

bool queue_empty()//判断是否为空
{
    if(tail==head)  return true;
    else            return false;
}

bool queue_full()//判断是否满
{
    if(head==tail+1||head==1&&tail==LEN)   return  true;
    else               return  false;
}






栈代码如下:

/*************************************************************************
	> File Name: stack.cpp
	> Author:chudongfang 
	> Mail:1149669942@qq.com 
	> Created Time: 2016年06月30日 星期四 10时28分24秒
 ************************************************************************/

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
int push(int key);
bool stack_empty();
int pop();
int stack[100];
int top=0;
int main(int argc,char *argv[])
{
    memset(stack,0,sizeof(stack));
    push(1);
    for(int i=1;i<=10;i++)
        printf("%d",stack[i]);
    printf("\ntop=%d\n",top);
    push(3);
    for(int i=1;i<=10;i++)
        printf("%d",stack[i]);
    printf("\ntop=%d\n",top);
    
    printf("pop=%d",pop());

    return 0;
}
int push(int key)//入栈
{
    top++;
    stack[top]=key;
}


bool stack_empty()//判断栈是否为空
{
    if(top==0)   return true;
    else         return false;
}


int pop()//出栈
{
    if(stack_empty())  
    {
        printf("the stack is empty!");
        return 0;
    }
    else
        return stack[top--];
}





链表:


双向链表,单向链表,循环链表。


其与数组不同的是,其在内存中不连续,用指针链接起来




指针和对象的实现


1.对象的多数组表示:


对象的每一个属性使用一个数组表示,可以用来表示

一组有相同属性的对象。


一个对象的所有属性的数组下标相同


key[]储存其关键值

next[]储存下一个节点位置

prev[]储存上一个节点位置


具体代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

int main(int argc,char *argv[])
{
    //该数组链表用来储存9->1->3
    int arry[20];

    memset(arry,0,sizeof(arry));
    int head=3;

    arry[3]=9;   //key
    arry[3+1] =7;//next
    arry[3+2] =0;//prev
   
   	arry[7]   =1;
    arry[7+1] =14;
    arry[7+2] =3;
   	
   	arry[14]  =3;
    arry[14+1] =0;
    arry[14+2] =7;

    for(int i=1;i<=19;i++)
    	printf("%d ",arry[i]);

    return 0;
}





2.对象的单数组表示


在一个数组中指针仅仅是该对象所在的第一个储存单元的地址,

要访问对象其他储存单元可以在指针上加上一个偏移量。


例如keynext prev对应的偏移量分别为0,1,2


则访问其时只需根据偏移量找到其元素


下面看例子的对应代码:

/*************************************************************************
	> File Name: single_attay.cpp
	> Author:chudongfang 
	> Mail:1149669942@qq.com 
	> Created Time: 2016年06月30日 星期四 11时08分58秒
 ************************************************************************/


#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include <algorithm>
#define INF 0x3f3f3f3f
#define N 6
using namespace std;
typedef long long ll;

int main(int argc,char *argv[])
{
    //该数组链表用来储存9->1->3
    int next[N];//下一个节点位置
    int key[N];//关键值
    int prev[N];//上一个节点位置
    int head;
    memset(next,0,sizeof(next));
    memset(key,0,sizeof(key));
    memset(prev,0,sizeof(prev));
    head=3;

    key[3] =9;
    next[3]=5;
    
    key[5] =1;
    next[5]=2;
    prev[5]=3;
    
    prev[2]=5;
    key[2] =3;
        
    for(int i=1;i<N;i++)
        printf("%d ",next[i]);
    printf("\n");
    for(int i=1;i<N;i++)
        printf("%d ",key[i]);
    printf("\n");
    for(int i=1;i<N;i++)
        printf("%d ",prev[i]);

    return 0;
}








对象的分配与释放


用一个头节点为free的链表(自由表),表示其空余的空间,

然后对自由表进行操作,进行空间的分配与释放。



来看代码:

/*************************************************************************
	> File Name: 10.3_objetc.cpp
	> Author:chudongfang 
	> Mail:1149669942@qq.com 
	> Created Time: 2016年06月30日 星期四 09时12分15秒
 ************************************************************************/

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include <algorithm>
#define INF 0x3f3f3f3f
#define N 6
using namespace std;

int _free=0;

int allocate_object(int next[],int key[],int prev[]);
void free_object(int x,int next[]);

typedef long long ll;

int main(int argc,char *argv[])
{
    //该数组链表用来储存9->1->3
    int next[N];
    int key[N];
    int prev[N];
    int head;
    memset(next,0,sizeof(next));
    memset(key,0,sizeof(key));
    memset(prev,0,sizeof(prev));
    head=3;

    key[3] =9;
    next[3]=5;
    
    key[5] =1;
    next[5]=2;
    prev[5]=3;
    
    prev[2]=5;
    key[2] =3;
    
    
    for(int i=1;i<N;i++)
        printf("%d ",next[i]);
    printf("\n");
    for(int i=1;i<N;i++)
        printf("%d ",key[i]);
    printf("\n");
    for(int i=1;i<N;i++)
        printf("%d ",prev[i]);
    printf("\nfree=%d\n",_free);



    _free=1;//空链表头节点
    next[1]=4;
    printf("\n\n");
    for(int i=1;i<N;i++)
        printf("%d ",next[i]);
    printf("\n");
    for(int i=1;i<N;i++)
        printf("%d ",key[i]);
    printf("\n");
    for(int i=1;i<N;i++)
        printf("%d ",prev[i]);
    printf("\nfree=%d\n",_free);

    int temp=allocate_object(next,key,prev);
    if(temp==0)   printf("无可用的节点!\n");
    else 
        printf("\n\n%d可用",temp);//返回一个空的节点
    printf("\nfree=%d\n\n\n\n",_free);
    
    
    
    free_object(5,next);//释放节点5后的情况

    for(int i=1;i<N;i++)
        printf("%d ",next[i]);
    printf("\n");
    for(int i=1;i<N;i++)
        printf("%d ",key[i]);
    printf("\n");
    for(int i=1;i<N;i++)
        printf("%d ",prev[i]);
    printf("\nfree=%d\n",_free);

    return 0;
}
int allocate_object(int next[],int key[],int prev[])//根据空链表,返回一个可用的节点
{
    if(free==0)   return 0;
    else
    {
        int x=_free;
        _free=next[x];
        return x;
    }
}

void free_object(int x,int next[])//释放一个节点,并把其添加到空链表里
{
    next[x]=_free;
    _free=x;
}










其实可以多个链表共有一个自由表,而且多个链表自由表位置上

可能交错在一起,不过一个位置只能属于一个链表。



有根树的表示:



二叉树:


一个二叉树包括其父节点指针,指向左儿子节点的指针和

指向右儿子节点的指针还有其卫星数据。


父节点为NULL的表示其为根节点

如果没有左儿子,左儿子节点为NULL,没有右儿子,则右儿子节点为空。



多叉树:


利用左孩子右兄弟表示法:

每个节点都包含一个父节点指针p,且T.root指向树T的根节点。


其含有另外两个节点:


1.x.left-child指向节点x最左边的孩子节点


2.x.right-sibling指向x右侧的兄弟


如果节点没有孩子节点,则x.left-childNULL

如果节点x是其父节点的最右孩子,则x.right-siblingNULL





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值