C和指针 第17章 经典抽象数据类型 17.10 编程练习

这篇博客介绍了如何使用C语言实现动态分配的堆栈、队列和二叉搜索树。堆栈增加了resize_stack函数,队列模块通过动态数组和链表两种方式实现,同时提供了resize_queue函数。博客还展示了二叉搜索树的插入、查找和遍历操作。
摘要由CSDN通过智能技术生成

1. 在动态分配数组的堆栈模块中增加一个resize_stack函数。这个函数接受一个参数:堆栈的新长度。 
解析: 
#include <stdio.h>
#include <stdlib.h>
#include "stack.h" 

int main( void ){
    STACK_TYPE values[] = { 1, 2, 3, 4, 5 };
    size_t len = sizeof(values) / sizeof(*values);
    size_t i;
    size_t number;
    
    number = 4;
    create_stack( number );
    for( i = 0; i < number; ++i ){
        push( values[i] );
    }
    printf( "print elements in the stack:\n" );
    for( i = 0; i < number; ++i ){
        printf( "%d ", top() );
        pop();
    }
    printf( "\n" );
    destroy_stack();
    resize_stack( 5 );
    for( i = 0; i < len; ++i ){
        push( values[i] );
    }
    printf( "print elements in the stack:\n" );
    for( i = 0; i < len; ++i ){
        printf( "%d ", top() );
        pop();
    }
    printf( "\n" );
    destroy_stack();
    
    return EXIT_SUCCESS;
}

/*
** 动态数组堆栈 stack.h
*/
#include <stddef.h>
#define STACK_TYPE int /*堆栈所存储的值的类型。*/

/*
**create_stack
**创建堆栈。参数指定堆栈可以保存多少个元素。
**注意:这个函数并不用于静态数组版本的堆栈。 
*/ 
void create_stack( size_t size );

/*
**destroy_stack
**销毁堆栈。它释放堆栈所使用的内存。
**注意:这个函数也不用于静态数组版本的堆栈。
*/ 
void destroy_stack( void );

/*
**push
**把一个新值压入到堆栈中。它的参数是需要被压入的值。 
*/
void push( STACK_TYPE value );

/*
**pop
**从堆栈弹出一个值,并将它丢弃。
*/
void pop( void );

/*
**top
**返回堆栈顶部元素的值,但不对堆栈进行修改。
*/
STACK_TYPE top( void );

/*
**is_empty
**如果堆栈为空,返回TRUE,否则返回FALSE。
*/
int is_empty( void );

/*
**is_full
**如果堆栈已满,返回TRUE,否则返回FALSE。
*/
int is_full( void );

/*
**resize_stack
**参数指定堆栈可以重新设置为保存多少个元素。
*/

void resize_stack( size_t size );

/*
**一个用动态分配数组实现的堆栈。 
**堆栈的长度在创建堆栈的函数被调用时给出,该函数必须在任何其他操作堆栈的函数被调用之前调用。
*/
#include "stack.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <assert.h>
/*
**用于存储堆栈元素的数组和指向堆栈顶部元素的指针。 
*/ 
static STACK_TYPE *stack;
static size_t stack_size;
static int top_element = -1;

/*
**create_stack
*/
void
create_stack( size_t size ){
    assert( stack_size == 0 );
    stack_size = size;
    stack = (STACK_TYPE *)malloc( stack_size * sizeof( STACK_TYPE ) );
    assert( stack != NULL );

/*
**destroy_stack
*/
void
destroy_stack( void ){
    assert( stack_size > 0 );
    stack_size = 0;
    free( stack );
    stack = NULL;
}

/*
**push
*/
void
push( STACK_TYPE value ){
    assert( !is_full() );
    top_element += 1;
    stack[ top_element ] = value;
}

/*
**pop
*/
void
pop( void ){
    assert( !is_empty() );
    top_element -= 1;
}

/*
**top
*/
STACK_TYPE
top( void ){
    assert( !is_empty() );
    return stack[ top_element ];
}

/*
**is_empty
*/
int 
is_empty( void ){
    assert( stack_size > 0 );
    return top_element == -1;
}

/*
**is_full
*/
int
is_full( void ){
    assert( stack_size > 0 );
    return top_element == stack_size - 1;
}

/*
**resize_stack
**参数指定堆栈可以重新设置为保存多少个元素。
*/
void resize_stack( size_t size ){
    create_stack( size );
}
输出:

2.把队列模块转换为使用动态分配的数组形式,并增加一个resize_queue函数(类似于编程练习1)。
输出: 
#include <stdio.h>
#include <stdlib.h>
#include "queue.h"

int main( void ){
    QUEUE_TYPE values[] = { 1, 2, 3, 4, 5 };
    size_t len = sizeof(values) / sizeof(*values);
    size_t i;
    size_t number;
    
    number = 4;
    create_queue( number );
    for( i = 0; i < number; ++i ){
        insert( values[i] );
    }
    printf( "print elements in the queue:\n" );
    for( i = 0; i < number; ++i ){
        printf( "%d ", first() );
        delete();
    }
    printf( "\n" );
    destroy_queue();
    resize_queue( 5 );
    for( i = 0; i < len; ++i ){
        insert( values[i] );
    }
    printf( "print elements in the queue:\n" );
    for( i = 0; i < len; ++i ){
        printf( "%d ", first() );
        delete();
    }
    printf( "\n" );
    QUEUE_TYPE value;
    value = 5;
    insert( value );
    
    destroy_queue();
    
    return EXIT_SUCCESS;

}

/*queue.h头文件的内容如下:*/
/*
**一个队列模块的接口。
*/#include <stddef.h>
#define QUEUE_TYPE int /*队列元素的类型*/
/*
**创建一个队列,参数指定队列可以存储的元素的最大数量。
**注意:这个函数只适用于使用动态分配数组的队列。
*/
void create_queue( size_t size );

/*
**destroy_queue
**销毁一个队列。注意:这个函数只适用于链式和动态分配数组的队列。
*/
void destroy_queue( void );

/*
**insert
**向队列添加一个新元素,参数就是需要添加的元素。
*/
void insert( QUEUE_TYPE value );

/*
**delete
**从队列中移除1个元素并将其丢弃。 
*/
void delete( void );

/*
**first
**返回队列中第1个元素的值,但不修改队列本身。
*/
QUEUE_TYPE first( void );

/*
**is_empty
**如果队列为空,返回TRUE,否则返回FALSE。 
*/
int is_empty( void );
 
/*
**is_full
**如果队列已满,返回TRUE,否则返回FALSE。 
*/
int is_full( void );

/*
**resize_queue
**重新设置队列的大小。
*/
void resize_queue( size_t size ); 

/* queue.c文件的内容如下:*/
/*
**一个队列模块的接口。 
*/
#include <stddef.h>
#include <malloc.h>
#include <assert.h> 
#include "queue.h"

#define FALSE 0
#define TRUE 1

typedef struct QUEUE_PTR{
    QUEUE_TYPE *front;
    QUEUE_TYPE *rear;
} QueuePtr;

static QUEUE_TYPE *queue;
static QUEUE_TYPE queue_size;
static QueuePtr qp;

/*
**创建一个队列,参数指定队列可以存储的元素的最大数量。
**注意:这个函数只适用于使用动态分配数组的队列。
*/
void create_queue( size_t size ){
    assert( queue_size == 0 );
    queue_size = size;
    queue = (QUEUE_TYPE *)malloc( sizeof(QUEUE_TYPE) * queue_size );
    assert( queue != NULL );
    qp.front = queue;
    qp.rear = queue;
}

/*
**destroy_queue
**销毁一个队列。注意:这个函数只适用于链式和动态分配数组的队列。
*/
void destroy_queue( void ){
    assert( queue_size > 0 );
    queue_size = 0;
    free( queue );
    queue = NULL;
    qp.front = queue;
    qp.rear = queue;
}

/*
**insert
**向队列添加一个新元素,参数就是需要添加的元素。
*/
void insert( QUEUE_TYPE value ){
    assert( !is_full() );
    *qp.rear = value;
    qp.rear = qp.rear + 1;
}

/*
**delete
**从队列中移除1个元素并将其丢弃。 
*/
void delete( void ){
    assert( !is_empty() );
    qp.front = qp.front + 1; 
}

/*
**first
**返回队列中第1个元素的值,但不修改队列本身。
*/
QUEUE_TYPE first( void ){
    assert( !is_empty() );
    return *qp.front;
}

/*
**is_empty
**如果队列为空,返回TRUE,否则返回FALSE。 
*/
int is_empty( void ){
    assert( queue_size > 0 );
    if( qp.front == qp.rear  ){
        return TRUE;
    } else{
        return FALSE;
    }
}
 /*
**is_full
**如果队列已满,返回TRUE,否则返回FALSE。 
*/
int is_full( void ){
    assert( queue_size > 0 );
    if( qp.rear == queue + queue_size ){
        return TRUE;
    } else{
        return FALSE;
    }
}

/*
**resize_queue
**重新设置队列的大小。
*/
void resize_queue( size_t size ){
    create_queue( size );
}
输出:

3.把队列模块转换为链表实现。
解析:
这个转换类似链式堆栈,但是当最后一个元素被移除时,rear指针也必须被设置为NULL。 
#include "queue.h"
#include <stdio.h>
#include <stdlib.h>

int main( void ){
    QUEUE_TYPE values[] = { 1, 2, 3, 4, 5 };
    size_t len = sizeof(values) / sizeof(*values);
    size_t i;
    size_t number;
    
    number = 4;
    for( i = 0; i < number; ++i ){
        insert( values[i] );
    }
    printf( "print elements in the queue:\n" );
    for( i = 0; i < number; ++i ){
        printf( "%d ", first() );
        delete();
    }
    printf( "\n" );
    destroy_queue();
    for( i = 0; i < len; ++i ){
        insert( values[i] );
    }
    printf( "print elements in the queue:\n" );
    for( i = 0; i < len; ++i ){
        printf( "%d ", first() );
        delete();
    }
    printf( "\n" );
    QUEUE_TYPE value;
    value = 6;
    insert( value );
    printf( "print elements in the queue:\n" );
    for( i = 0; i < len + 1; ++i ){
        printf( "%d ", first() );
        delete();
    }
    destroy_queue();
    
    return EXIT_SUCCESS;
}

/*queue.h头文件的内容如下:*/
/*
** 一个用链表形式实现的队列,它没有长度限制。 
*/ 
#define QUEUE_TYPE int

/*
** destroy_queue
*/
void destroy_queue( void );

/*
** insert
*/
void insert( QUEUE_TYPE value );

/*
** delete
*/
void delete( void );

/*
** first
*/
QUEUE_TYPE first( void );

/*
** is_empty
*/
int is_empty( void );
/*
** is_full
*/
int is_full( void );

/* queue.c文件的内容如下:*/
/*
** 一个用链表形式实现的队列,它没有长度限制。 
*/ 
#include "queue.h" 
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

/*
** 定义一个结构用于保存一个值。link字段将指向队列中的下一个节点。 
*/
typedef struct QUEUE_NODE{
    QUEUE_TYPE value;
    struct QUEUE_NODE *next; 
} QueueNode;

/*
** 指向队列第1个和最后一个节点的指针。 
*/ 
static QueueNode *front;
static QueueNode *rear;

/*
** destroy_queue
*/ 

void destroy_queue( void ){
    while( !is_empty() ){
        delete();
    }
}

/*
** insert
*/
void insert( QUEUE_TYPE value ){
    QueueNode *new_node;
    
    /*
    ** 分配一个新节点,并填充它的各个字段。 
    */    
    new_node = (QueueNode *)malloc( sizeof(QueueNode) );
    assert( new_node != NULL );
    new_node->value = value;
    new_node->next = NULL;
    
    /*
    ** 把它插入到队列的尾部。 
    */ 
    if( rear == NULL ){
        front = new_node;
    } else{
        rear->next = new_node;
    }
    rear = new_node;
}

/*
** delete
*/
void delete( void ){
    QueueNode *next_node;
    
    /*
    ** 从队列的头部删除一个节点,如果它是最后1个节点,
    ** 将rear也设置为NULL。
    */
    assert( !is_empty() );
    next_node = front->next;
    free( front );
    front = next_node;
    if( front == NULL ){
        rear = NULL;
    } 
}

/*
** first
*/
QUEUE_TYPE first( void ){
    assert( !is_empty() );
    return front->value;
}

/*
** is_empty
*/
int is_empty( void ){
    return front == NULL;
}

/*
** is_full
*/
int is_full( void ){
    return 0;
}
输出:

4.堆栈,队列和树模型如果可以处理超过一个的堆栈、队列和树,它们会更加实用。修改动态数组堆栈模型,使它最多可以10个不同的堆栈。此时需要修改堆栈函数的接口,使它们接受另一个参数---需要使用的堆栈的索引。 
解析: 
/*
**一个使用泛型堆栈模块创建两个容纳不同类型数据的堆栈的用户程序
*/
#include <stdlib.h>
#include <stdio.h>
#include "stack.h"

/*
**创建三个堆栈,两个用于容纳整数,另一个用于容纳浮点值。
*/
GENERIC_STACK( int, _int, 10, _1 )
GENERIC_STACK( int, _int, 10, _2 )
GENERIC_STACK( float, _float, 5, _1 )

int main( void ) {
    /*
    **往每个堆栈压入几个值。 
    */
    create_stack_int_1();
    push_int_1( 5 );
    push_int_1( 22 );
    push_int_1( 15 );
    
    create_stack_int_2();
    push_int_2( 6 );
    push_int_2( 23 );
    push_int_2( 16 );
    
    create_stack_float_1();
    push_float_1( 25.3 );
    push_float_1( -40.5 );
    
    /*
    **清空第一个整数堆栈并打印这些值。 
    */
    while( !is_empty_int_1() ){
        printf( "Popping %d\n", top_int_1() );
        pop_int_1();
    }
    destroy_stack_int_1();
    
    /*
    **清空第二个整数堆栈并打印这些值。 
    */
    while( !is_empty_int_2() ){
        printf( "Popping %d\n", top_int_2() );
        pop_int_2();
    } 
    destroy_stack_int_2();
    
    /*
    **清空浮点数堆栈并打印这些值。
    */
    while( !is_empty_float_1() ){
        printf( "Popping %f\n", top_float_1() );
        pop_float_1();
    } 
    destroy_stack_float_1();
    
    return EXIT_SUCCESS;

/* stack.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_40186813

你的能量无可限量。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值