、 首先,这对两个结构体,我觉得写的很好。可读性也很强,第一个结构体写的是节点,第二个结构体是整个链栈,很清晰。其次,我并没有觉得它有哪个地方占用了很大的内存空间,除了节点处,基本没有其他内存占用。把节点独立出来,使得操作更方便,写节点的时候不用考虑其他的,写链栈的时候也不需要管链表,只要知道链表首地址和节点数就行了。两者之间联系越小,考虑就越简单,操作越简单,可读性越好。 其实,lz可以学习下这种处理方式。把数据和结构独立出来,把结构和操作联系起来,这样写出来的代码会更好,层次性也会更强。 #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:17 编辑
里面我没怎么测试,期末考试临近,我也得复习。你可以自己测试下。用面向对象的思考方式学习数据结构,你会对数据结构有更深的理解。 q5603113 发表于 2012-6-12 20:13 static/image/common/back.gif
可我代码对比了一下,还是找不到这种代码的好处在那里,可能我对数据结构的理解还不够深刻吧
其实我的代码也写得很一般般的。我也只是写出自己的一点理解而已,也还有很多需要学习的地方 // 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]