演算法導論_第十章_基本資料結構

chudongfang2015發表於2016-06-30


演算法導論_第十章_基本資料結構

佇列和棧:


佇列為先進先出,棧為先進後出。


其可以用陣列和連結串列實現。



佇列程式碼如下

/*************************************************************************
	> 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





相關文章