q5603113 发表于 2012-6-11 13:33:41

chao_prince 发表于 2012-6-11 14:40:09

首先,楼主的代码似乎有很多手误的敲错的地方。。其次,这种方法是定义了一个头结点和尾结点,各种方法都有好有坏,根据各人喜好,或者需求来选择,定义头结点的好处在于,对于插入和删除编码比较方便,不用考虑空表的特殊情况,至于尾结点,可以让在尾部插入比较方便。。

q5603113 发表于 2012-6-11 14:50:10

故乡的风 发表于 2012-6-12 10:08:19

首先,这对两个结构体,我觉得写的很好。可读性也很强,第一个结构体写的是节点,第二个结构体是整个链栈,很清晰。其次,我并没有觉得它有哪个地方占用了很大的内存空间,除了节点处,基本没有其他内存占用。把节点独立出来,使得操作更方便,写节点的时候不用考虑其他的,写链栈的时候也不需要管链表,只要知道链表首地址和节点数就行了。两者之间联系越小,考虑就越简单,操作越简单,可读性越好。

故乡的风 发表于 2012-6-12 10:10:39

其实,lz可以学习下这种处理方式。把数据和结构独立出来,把结构和操作联系起来,这样写出来的代码会更好,层次性也会更强。

q5603113 发表于 2012-6-12 11:45:41

故乡的风 发表于 2012-6-12 16:12:24

#include <stdio.h>
#include <stdlib.h>

typedef int ElemType;

typedef int BOOL;
#define TRUE1
#define FALSE 0

//链栈节点
typedef struct StackNode {
        ElemType data;
        struct StackNode *next;
} StackNode, *LinkStackPtr;

//链栈
typedef struct LinkStack {
        LinkStackPtr top;        //栈顶
        int count;                        //节点数
} LinkStack;

//初始化链栈
BOOL InitStack(LinkStack &stack) {
        stack.top = NULL;
        stack.count = 0;

        return TRUE;
}

//入栈
BOOL Push(LinkStack &stack, LinkStackPtr pStackNode) {
        //判断节点是否为空
        if (pStackNode == NULL) {
                printf("Node doesn't exist!");
                return FALSE;
        }

        //新节点入栈
        pStackNode->next = stack.top;
        stack.top = pStackNode;        //新栈顶
        stack.count++;        //节点数+1

        return TRUE;
}

//出栈
BOOL Pop(LinkStack &stack, LinkStackPtr &pStackNode) {
        //判断是否栈空
        if (stack.count == 0) {
                printf("Stack empty!");
                return FALSE;
        }

        //取出节点
        pStackNode = stack.top;
        stack.top = stack.top->next;
        pStackNode->next = NULL;
        //节点数-1
        stack.count--;

        return TRUE;
}

//创建节点
LinkStackPtr CreateNode(ElemType data) {
        //申请空间
        LinkStackPtr pNode = (LinkStackPtr)malloc(sizeof(StackNode));
        //申请失败
        if (pNode == NULL) {
                printf("Cannot apply for enough memory.");
                return NULL;
        }

        pNode->data = data;
        pNode->next = NULL;
        return pNode;
}

//取出节点数据
ElemType GetData(LinkStackPtr pNode) {
        return pNode->data;
}

int main(int argc, char** argv) {
        //初始化栈
        LinkStack stack;
        InitStack(stack);

        //为了方便,我就直接赋值做测试了,
        //有效性检测也省了不写了
        ElemType data;
        LinkStackPtr pNode;
        for (int i = 0; i < 5; ++i) {
                data = i;
                pNode = CreateNode(data);
        }

        //入栈
        Push(stack, pNode);
        Push(stack, pNode);
        Push(stack, pNode);

        //出栈
        LinkStackPtr pTemp = NULL;
        Pop(stack, pTemp);
        printf("%d\n", GetData(pTemp));

        return 0;
}

故乡的风 发表于 2012-6-12 16:15:33

本帖最后由 故乡的风 于 2012-6-12 16:17 编辑

里面我没怎么测试,期末考试临近,我也得复习。你可以自己测试下。用面向对象的思考方式学习数据结构,你会对数据结构有更深的理解。

q5603113 发表于 2012-6-12 20:13:20

故乡的风 发表于 2012-6-13 09:36:53

q5603113 发表于 2012-6-12 20:13 static/image/common/back.gif
可我代码对比了一下,还是找不到这种代码的好处在那里,可能我对数据结构的理解还不够深刻吧
其实我的代码也写得很一般般的。我也只是写出自己的一点理解而已,也还有很多需要学习的地方

chao_prince 发表于 2012-6-13 21:52:59

// Stack.h
typedef int ElementType;

#ifndef STACK_H_
#define STACK_H_

// 结点的前向声明,具体实现在.c文件
struct Node;
typedef struct Node *PtrToNode;
typedef PtrToNode Stack;

int IsEmpty( Stack S );
Stack CreateStack( void );
void DestroyStack( Stack *S );
void MakeEmpty( Stack S );
void Push( ElementType X, Stack S );
// 返回栈顶元素
ElementType Top( Stack S );
// 只弹出栈顶元素,不返回此元素
void Pop( Stack S );
// 弹出栈顶元素,同时返回此元素
ElementType TopAndPop( Stack );
#endif// Stack.c
#include "Stack.h"
#include <stdlib.h>
#include <assert.h>

struct Node{
        ElementType Element;
        PtrToNode Next;
};

int IsEmpty( Stack S )
{
        return S->Next == NULL;
}

//************************************
// Method:    CreateStack
// FullName:CreateStack
// Access:    public
// Returns:   Stack
// Qualifier: 链式堆栈,链表带头结点
// Parameter: void
//************************************
Stack CreateStack( void )
{
        Stack S;
       
        S = malloc( sizeof( struct Node ) );
        assert( S != NULL );
        S->Next = NULL;

        MakeEmpty( S );

        return S;
}

void MakeEmpty( Stack S )
{
        assert( S != NULL );

        while( !IsEmpty( S ) )
                Pop( S );
}

void DestroyStack( Stack *S )
{
        MakeEmpty( *S );
        free( *S );

        // 将头结点释放后置为NULL,
        // 防止悬挂指针
        *S = NULL;
}

void Push( ElementType X, Stack S )
{
        PtrToNode TmpCell;

        TmpCell = malloc( sizeof( struct Node ) );
        assert( TmpCell != NULL );

        TmpCell->Element = X;
        TmpCell->Next = S->Next;
        S->Next = TmpCell;
}

ElementType Top( Stack S )
{
        // 确保S不为空栈
        assert( !IsEmpty( S ) );

        return S->Next->Element;
}

void Pop( Stack S )
{
        PtrToNode FirstCell;

        // 确保S不为空栈
        assert( !IsEmpty( S ) );

        FirstCell = S->Next;
        S->Next = FirstCell->Next;
        free( FirstCell );
}

ElementType TopAndPop( Stack S )
{
        PtrToNode FirstCell;
        ElementType X;

        // 确保S不为空栈
        assert( !IsEmpty( S ) );

        FirstCell = S->Next;
        X = FirstCell->Element;
        S->Next = FirstCell->Next;
        free( FirstCell );

        return X;
}// TestStack.c
#include "Stack.h"
#include <stdio.h>

int main()
{
        Stack S = NULL;

        S = CreateStack();

        Push( 520, S );
        Push( 1314, S );

        while( !IsEmpty(S) )
                printf( "出栈元素是: %d\n", TopAndPop(S) );

        return 0;
}
页: [1]
查看完整版本: 谁来答我心中的疑惑