标题:分享:泛型队列
只看楼主
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
结帖率:95.65%
 问题点数:0 回复次数:9 
分享:泛型队列
最近一点做题看书的心情的都没有。
数据结构停在了二叉树,看来会停很久。
所以……今天有时间完成了一个月以前就该完成的事,拿出来分享给大家。
虽然完全不知道大家是否对此感兴趣。


程序代码:
//测试:
#include "queue.h"
#include <stdio.h>
MakeQueue( int, _int )
MakeQueue( char, _char )

int
main( void )
{
    int ix;

    Create_int();
    Create_char();

    for( ix = 0; 20 > ix; ++ix )
    {
        Insert_int( ix );
        Insert_char( 'a' + ix );
    }

    printf( "队列1:\n" );
    while( !Is_Empty_int() )
    {
        printf( "%d ",First_int() );
        Delete_int();
    }

    printf( "\n队列2:\n" );
    while( !Is_Empty_char() )
    {
        printf( "%c ",First_char() );
        Delete_char();
    }

    Destroy_int();
    Destroy_char();

    return 0;
}



程序代码:
//泛型队列:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define INITSIZE 128
#define MakeQueue( ElementType, Name )                                                \
    void Insert##Name( ElementType Value );                                            \
    ElementType First##Name( void );                                            \
    void Delete##Name( void );                                                \
    int Is_Full##Name( void );                                                \
    int Is_Empty##Name( void );                                                \
    void Destroy##Name( void );                                                \
    void Create##Name( void );                                                \
                                                                \
    static ElementType *Queue##Name;                                            \
    static int CurrentSize##Name = INITSIZE;                                        \
    static int Frnot##Name = 1;                                                \
    static int Read##Name = 0;                                                \
                                                                \
                                                                \
    void Insert##Name( ElementType Value )                                            \
    {                                                            \
        assert( !Is_Full##Name() );                                            \
        assert( NULL != Queue##Name );                                            \
        Read##Name =  ( Read##Name + 1 ) % CurrentSize##Name;                                \
        Queue##Name[ Read##Name ] = Value;                                        \
    }                                                            \
                                                                \
                                                                \
    ElementType First##Name( void )                                                \
    {                                                            \
        assert( !Is_Empty##Name());                                            \
        assert( NULL != Queue##Name );                                            \
        return Queue##Name[ Frnot##Name ];                                        \
    }                                                            \
                                                                \
                                                                \
    void Delete##Name( void )                                                \
    {                                                            \
        assert( !Is_Empty##Name() );                                            \
        assert( NULL != Queue##Name );                                            \
        Frnot##Name = ( Frnot##Name + 1 ) % CurrentSize##Name;                                \
    }                                                            \
                                                                \
    int Is_Full##Name( void )                                                \
    {                                                            \
        int i;                                                        \
        ElementType *Temp;                                                \
                                                                \
        assert( NULL != Queue##Name );                                            \
        i = ( Read##Name + 2 ) % CurrentSize##Name;                                    \
                                                                \
        if( i == Frnot##Name )                                                \
        {                                                        \
            CurrentSize##Name += INITSIZE;                                        \
            Temp = ( ElementType * )realloc( Queue##Name, CurrentSize##Name * sizeof( ElementType ) );        \
            if( NULL == Temp )                                            \
            {                                                    \
                CurrentSize##Name -= INITSIZE;                                    \
                return 1;                                            \
            }                                                    \
            Queue##Name = Temp;                                            \
            return 0;                                                \
        }                                                        \
                                                                \
        return 0;                                                    \
    }                                                            \
                                                                \
                                                                \
    int Is_Empty##Name( void )                                                \
    {                                                            \
        return ( Read##Name + 1 ) % CurrentSize##Name == Frnot##Name;                            \
    }                                                            \
                                                                \
                                                                \
    void Create##Name( void )                                                \
    {                                                            \
        assert( NULL == Queue##Name );                                            \
        if( NULL == ( Queue##Name = ( ElementType * )malloc( CurrentSize##Name * sizeof( ElementType ) ) ) )        \
            exit( EXIT_FAILURE );                                            \
    }                                                            \
                                                                \
                                                                \
    void Destroy##Name( void )                                                \
    {                                                            \
        assert( NULL != Queue##Name );                                            \
        free( Queue##Name );                                                \
        Queue##Name = NULL;                                                \
        CurrentSize##Name = INITSIZE;                                            \
        Frnot##Name = 1;                                                \
        Read##Name = 0;                                                    \
    }


[此贴子已经被作者于2017-4-22 10:25编辑过]

搜索更多相关主题的帖子: 二叉树 心情 
2017-04-21 20:21
yangfrancis
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:贵宾
威 望:141
帖 子:1510
专家分:7661
注 册:2014-5-19
得分:0 
楼主能否用白话科普一下什么是泛型队列,还有,希望解释一下##是什么语法现象,有何用途。谢谢
2017-04-21 20:36
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 2楼 yangfrancis
举例:你要建立一个队列,但是队列中存储数据的类型是必须一开始就决定。
那么……在这种情况下,你需要另一个(或多个)不同数据类型的队列,你就需要再写一遍代码,而这一次所写的代码和上一次所写的代码几乎一模一样(除了函数的名字)。

泛型不是C语言的概念。(C11增加了一个泛型关键字,但我不会用)。

##是#define的链接符,作用是将2个token连接起来形成一个新的token。

不对吧,你是C++版的版主,你不知道什么是泛型?

[此贴子已经被作者于2017-4-21 21:01编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-21 20:47
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
多谢楼主分享~这个要顶~~~~~

以下是引用renkejun1942在2017-4-21 20:21:58的发言:

最近一点做题看书的心情的都没有。
数据结构停在了二叉树,看来会停很久。


期待楼主分享二叉树啊~我做到AVL树和哈夫曼编码就卡了~~楼主加油啊~挺你~~

[此贴子已经被作者于2017-4-21 22:44编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-04-21 22:41
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
以前在宏名称合并这部分纠结了很久~现在看了 /的作用就是转义每一行都要加一次~有些多余的空行删了也可以~
楼主能否讲解一下/的具体作用?~~~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-04-21 22:50
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 5楼 九转星河
\的作用就是连接。

\在很多地方都可以用,比如printf().

举例:如果一行太长,就可以加一个\。
printf("。。。。。。。。。。。。。。。。。。。。。。。。。");
可以写成:
printf("。。。。。。。。。。\
。。。。。。。。。。。。。。。");

当然,这种截断、连接,有好多个写法,但是在宏里面就只有\一个办法了。

##的作用在3楼也说了,它将两个token连接成一个新的token,举例:第一个token是a,第二个是123,连接之后就是a123,但是这种连接生成的token必须是合法的token才可以。
曾经我也在##上蹉跎了好些岁月,完全搞不懂。

[此贴子已经被作者于2017-4-21 23:03编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-21 22:54
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
回复 6楼 renkejun1942
感觉\的功能在这里起到截断作用~宏展开要从最底层开始~往上一层一层展开~其实不加\就等效于把所有宏都写到一行上~~不过感觉这样要连续写中间不能断~例如我打算中间放个main函数后再接着写还没有写完的宏定义就行不通了~~

预编译不会检查展开宏里面的语句是否合法~里面的语句要在正式编译的时候代入宏参数才有意义~

简单的代码如下~
程序代码:
#include<stdio.h>
#define MAKE_FUN(NAME)  int FUN##NAME() {return 1;}
MAKE_FUN(get_id);
int main()
{
    printf("%d\n",FUNget_id());

    return 0;
}


感觉就是定义一个宏就是申明一个几乎重复的代码~系统编译预留的堆空间没有省~
而且申明函数必须要在main开始前进行函数申明~这就意味着其实在预编译时就已经申明和定义了大量库函数了~不过这样写还是可以大大减少代码量的~~

另外提示一句~宏的坑有很多<<C语言陷阱>>里面提及过~一些看上去像库函数的东西或许不是函数而是一个宏~所以使用方面要格外注意一下~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-04-22 02:02
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 7楼 九转星河
我不清楚宏怎么展开,但是我知道宏展开是什么样子。

不过,使用宏的确要非常小心。

你的写法的确是可以的,但是宏本身就很丑了,你再不进行缩进、换行、空行,那就更丑了。


[此贴子已经被作者于2017-4-22 10:24编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-04-22 09:20
yangfrancis
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:贵宾
威 望:141
帖 子:1510
专家分:7661
注 册:2014-5-19
得分:0 
回复 3楼 renkejun1942
不知道泛型。没接触过
2017-04-22 17:05
邹特强
Rank: 2
等 级:论坛游民
帖 子:123
专家分:85
注 册:2016-9-21
得分:0 
回复 3楼 renkejun1942
哈哈,泛型不是面对对象语言里的吗,我学java时学过,原来c语言也有泛型

............
2017-05-17 12:28



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-476326-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.177393 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved