| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4009 人关注过本帖
标题:分享:通用栈(如果你有任何疑问或建议,请提出)
取消只看楼主 加入收藏
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
结帖率:95.65%
收藏
已结贴  问题点数:100 回复次数:12 
分享:通用栈(如果你有任何疑问或建议,请提出)
栈、队列、链表的通用,到此刻算是彻底完成了。
三种ADT,三种不同的实现思路。

还是老样子,如果你有任何问题或建议,情提出。

21:02 5/18
修正了void *进行数学计算的问题,现在应该不会再报错了。

22:32 5/19
删除了实现文件中多余的宏。
DestroyStack()函数增加了几行代码,当最后一个栈被销毁,则释放掉全局变量STACK指向的空间。
但似乎这样做并不是很有必要,先就这样。


程序代码:
//测试:
#include "Stack.h"
#include <stdio.h>


int
main( void )
{
    Stack_T a, c;
    int *b;
    int ix;
    char ch;
    char *k;

    a = CreateStack( sizeof( int ) );
    c = CreateStack( sizeof( char ) );

    for( ix = 0; 200 > ix; ++ix )
    {
        PoshStack( a, &ix );
        ch = 'a' + ( ix % 26);
        PoshStack( c, &ch );
    }

    while( !IsEmptyStack( a ) )
    {
        b = TopStack( a );
        printf( "%d ", *b );
        PopStack( a );
    }

    DestroyStack( a );
    printf( "\n" );

    while( !IsEmptyStack( c ) )
    {
        k = TopStack( c );
        printf( "%c ", *k );
        PopStack( c );
    }

    DestroyStack( c );

    return 0;
}


程序代码:

//接口:
#ifndef __STACK_H__
#define __STACK_H__
#include <stdio.h>
#define T Stack_T
typedef int T;

T
CreateStack( size_t DataSize );//创建一个栈,参数为数据的大小,成功返回栈。

int
DestroyStack( T Stack );//销毁一个栈,参数为需要销毁的栈,成功返回0,失败返回1

void
PoshStack( T Stack, void *Value );//将一个值压入栈,参数为栈和需要入栈的元素。

void *
TopStack( T Stack );//将一个值从栈顶弹出,参数为需要弹出值的栈,成功返回指向该元素的指针。

void
PopStack( T Stack );//从一个栈中删除栈顶元素,参数为需要删除值的栈

int
IsEmptyStack( T Stack );//检测栈是否为空,参数为需要检测的栈,如果为空,返回1,否则返回0

int
IsFullStack( T Stack );//检测栈是否已满,参数为需要检测的栈,如果已满返回1,否则返回0

#undef T
#endif



程序代码:
//实现

#include "Stack.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define T Stack_T
#define L list
#define INITSIZE 128
#define INITUP 10

typedef struct L *L;
struct L{
    void *Element;
    void *Top;
    int Step;
    int CurrentSize;
};

static L *STACK;
static int ThisSize;


T
CreateStack( size_t DataSize )
{
    int ix;
    L *Temp;

    if( NULL == STACK )
    {
        ThisSize = INITUP;
        STACK = ( L * )malloc( ThisSize * sizeof( L ) );
        if( NULL == STACK )
            exit( EXIT_FAILURE );
        for( ix = 0; ThisSize > ix; ++ix )
            STACK[ ix ] = NULL;
    }

    for( ix = 0; ThisSize > ix && NULL != STACK[ ix ]; ++ix )
        ;

    if( ThisSize == ix )
    {
        ThisSize += INITUP;
        Temp = ( L * )realloc( STACK, ThisSize * sizeof( L ) );
        if( NULL == Temp )
            exit( EXIT_FAILURE );
        STACK = Temp;
        for( int i = ix; ThisSize > i; ++i )
            STACK[ i ] = NULL;
    }

    STACK[ ix ] = malloc( sizeof( struct L ) );
    if( NULL == STACK[ ix ] )
        exit( EXIT_FAILURE );

    STACK[ ix ]->Element = malloc( INITSIZE * DataSize );
    if( NULL == STACK[ ix ]->Element )
        exit( EXIT_FAILURE );

    STACK[ ix ]->Top = STACK[ ix ]->Element;
    STACK[ ix ]->Step = DataSize;
    STACK[ ix ]->CurrentSize = INITSIZE;

    return ix;
}

int
DestroyStack( T Stack )
{
    int ix;

    if( 0 > Stack || ThisSize <= Stack || NULL == STACK[ Stack ] )
        return 1;

    free( STACK[ Stack ]->Element );
    free( STACK[ Stack ] );
    STACK[ Stack ] = NULL;

    for( ix = 0; ThisSize > ix; ++ix )
        if( NULL != STACK[ ix ] )
            break;
    if( ThisSize == ix )
    {
        free( STACK );
        ThisSize = 0;
    }

    return 0;
}

void
PoshStack( T Stack, void *Value )
{
    if( 0 > Stack || ThisSize <= Stack || NULL == STACK[ Stack ] )
        return;

    if( !IsFullStack( Stack ) )
    {
        memmove( STACK[ Stack ]->Top, Value, STACK[ Stack ]->Step );
        STACK[ Stack ]->Top = ( char * )( STACK[ Stack ]->Top ) + STACK[ Stack ]->Step;
    }
    else
        return;
}

void *
TopStack( T Stack )
{

    if( 0 > Stack || ThisSize <= Stack || NULL == STACK[ Stack ] )
        return NULL;

    if( !IsEmptyStack( Stack ) )
        return ( char * )( STACK[ Stack ]->Top ) - STACK[ Stack ]->Step;
    else
        return NULL;
}


void
PopStack( T Stack )
{
    if( 0 > Stack || ThisSize <= Stack ||NULL == STACK[ Stack ] )
        return;

    if( !IsEmptyStack( Stack ) )
        STACK[ Stack ]->Top = ( char * )( STACK[ Stack ]->Top ) - STACK[ Stack ]->Step;
}

int
IsEmptyStack( T Stack )
{
    if( 0 > Stack || ThisSize <= Stack || NULL == STACK[ Stack ] )
        return 1;

    return STACK[ Stack ]->Top == STACK[ Stack ]->Element;
}

int
IsFullStack( T Stack )
{
    int c;
    void *Temp;

    if( 0 > Stack || ThisSize <= Stack || NULL == STACK[ Stack ] )
        return 1;

    c = ( ( char * )( STACK[ Stack ]->Top ) - ( char * )( STACK[ Stack ]->Element ) ) / STACK[ Stack ]->Step;

    if( STACK[ Stack ]->CurrentSize == c + 1 )
    {
        STACK[ Stack ]->CurrentSize += INITSIZE;
        Temp = realloc( STACK[ Stack ]->Element, 
                STACK[ Stack ]->CurrentSize * STACK[ Stack ]->Step );
        if( NULL == Temp )
            return 1;
        STACK[ Stack ]->Element = Temp;
        STACK[ Stack ]->Top = ( char * )( STACK[ Stack ]->Element ) + c * STACK[ Stack ]->Step;
        return 0;    
    }
    else
        return 0;
}








[此贴子已经被作者于2017-5-20 11:50编辑过]

搜索更多相关主题的帖子: 通用 空间 
2017-05-18 19:28
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 2楼 九转星河
不要把接口文件和实现文件的代码合并在一起。

你的错误警告,我看看先。你截取全部呢?

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-18 19:58
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 4楼 九转星河
你写通用链表的时候,使用void指针会报错吗?
貌似不会的吧?怎么到这里就会报错了。

你知道的,接口就是一个头文件。
在需要调用接口中函数的文件中 #include 就可以了。

实现文件需要和main()函数的文件一起编译。

VC的话,我不知道怎么多文件编译。

VS2015怎么操作,我倒知道。
这是一个示例,当时做通用链表的时候截的图。
图片附件: 游客没有浏览图片的权限,请 登录注册


[此贴子已经被作者于2017-5-18 20:03编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-18 20:02
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 2楼 九转星河
你的文件的后缀,看一下是不是.c,如果不是的话,记得改成.c

c++的void指针不允许进行数学计算。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-18 20:12
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 7楼 九转星河
你的文件名后缀真的是.c吗?截个图来看看呢?
unsigned int 的问题,我改掉了,改成了 int

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-18 20:18
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 9楼 九转星河
嗯,看来我需要查一下void指针是什么时候进入标准的了。


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-18 20:20
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 11楼 九转星河
unsigned 你自己把它删掉,改成int就行了。

void *改成 char *

看来VC甚至不完全支持C89

如果我没记错的话,void指针是C89标准。

[此贴子已经被作者于2017-5-18 20:27编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-18 20:26
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
void * 的问题,是我的编译器的问题,我的编译器对这个类型做出了扩展。

我修改一下代码。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-18 20:53
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 17楼 九转星河
如果一个栈被销毁,那么那个位置的确处于‘空’的状态。
如果再一次申请建立栈,那个‘空’着的位置就会被再次分配出去。

用数组的基本目的是为了好看,多个不同的栈整整齐齐的排列在哪里。

另外,隐藏细节。

[此贴子已经被作者于2017-5-21 05:57编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-21 05:53
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 19楼 九转星河
10 或20个元素的遍历好快的。

隐藏细节这点,你查一下封装,就清楚了。似乎你只是单纯的知道封装,却不知道为什么要封装。

[此贴子已经被作者于2017-5-21 08:36编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-21 08:32
快速回复:分享:通用栈(如果你有任何疑问或建议,请提出)
数据加载中...
 
   



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

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