建立3個文件:stackLinked.h、stackLinked.c、stackLinkedTest.c
stackLinked.h
#ifndef STACK_LINKED_H_ #define STACK_LINKED_H_ #ifdef __GNUC__ #define DEPRECATED __attribute__( (deprecated) ) #elif defined(_MSC_VER) #define DEPRECATED __declspec( deprecated ) #else #define DEPRECATED #endif #ifndef PTOI #define PTOI( p ) ((int32_t)(int64_t)(p)) #endif #ifndef ITOP #define ITOP( i ) ((void *)(int64_t)(i)) #endif #define ADT StackLinked // 功能: a與b的比較過程. // 參數: a, b. // 返回: a>b返回正數, a<b返回負數, 不然返回0. // 注意: a不爲NULL且b爲NULL,返回正數, a爲NULL且b不爲NULL,返回負數, a與b都爲NULL,返回0. typedef int ( CompareFunc )( const void *a, const void *b ); typedef struct StackLinked StackLinked; // 功能: 建立新的棧. // 參數: 無. // 返回: 新的棧. // 注意: 當內存分配失敗時,將錯誤退出程序. extern ADT *newStackLinked( void ); // 功能: 將用戶數據壓入到棧頂. // 參數: stack(棧對象的指針), data(用戶數據). // 返回: 被壓入棧頂的用戶數據. // 注意: 當 stack 爲NULL 時, 將錯誤退出程序. extern void *pushStackLinked( ADT *stack, void *data ); // 功能: 彈出棧頂用戶數據. // 參數: stack(棧對象的指針). // 返回: 被彈出的棧頂的用戶數據. // 注意: 當 stack 爲NULL 或 空棧狀態 時, 將錯誤退出程序. extern void *popStackLinked( ADT *stack ); // 功能: 偷看棧頂的用戶數據. // 參數: stack(棧對象的指針). // 返回: 棧頂的用戶數據. // 注意: 當 stack 爲NULL 或 空棧狀態 時, 將錯誤退出程序. extern void *peekStackLinked( ADT *stack ); // 功能: 偷看棧底的用戶數據. // 參數: stack(棧對象的指針). // 返回: 棧底的用戶數據. // 注意: 當 stack 爲NULL 或 空棧狀態 時, 將錯誤退出程序. extern void *peekBottomStackLinked( ADT *stack ); // 功能: 棧中全部用戶數據中是否包含了data. // 參數: stack(棧對象的指針), data(需查找的用戶數據), cmp(比較函數的指針). // 返回: 包含data返回1, 不然返回0. // 注意: 當 stack 爲NULL 或 cmp 爲NULL 時, 將錯誤退出程序. extern int existStackLinked( ADT *stack, void *data, CompareFunc *cmp ); // 功能: 從棧頂至棧底方向查找data. // 參數: stack(棧對象的指針), data(需查找的用戶數據), cmp(比較函數的指針). // 返回: 包含data, 返回data所在位置, 不然返回-1. // 注意: 當 stack 爲NULL 或 cmp 爲NULL 時, 將錯誤退出程序. extern int32_t findStackLinked( ADT *stack, void *data, CompareFunc *cmp ); // 功能: 從棧底至棧頂方向查找data. // 參數: stack(棧對象的指針), data(需查找的用戶數據). // 返回: 包含data, 返回data所在位置, 不然返回-1, cmp(比較函數的指針). // 注意: 當 stack 爲NULL 或 cmp 爲NULL 時, 將錯誤退出程序. extern int32_t findTailStackLinked( ADT *stack, void *data, CompareFunc *cmp ); // 功能: 棧實際已使用大小. // 參數: stack(棧對象的指針). // 返回: 棧實際已使用大小. // 注意: 當 stack 爲NULL 時, 將錯誤退出程序. extern int32_t sizeStackLinked( ADT *stack ); // 功能: 空棧狀態. // 參數: stack(棧對象的指針). // 返回: 是空棧返回1, 不然返回0. // 注意: 當 stack 爲NULL 時, 將錯誤退出程序. extern int emptyStackLinked( ADT *stsack ); // 功能: 反轉棧. // 參數: stack(棧對象的指針). // 返回: 無. // 注意: 當 stack 爲NULL 時, 將錯誤退出程序. extern void reversalStackLinked( ADT *stack ); // 功能: 滿棧狀態. // 參數: stack(棧對象的指針). // 返回: 是滿棧返回1, 不然返回0. // 注意: 當 stack 爲NULL 時, 將錯誤退出程序. // 被棄用的函數. extern DEPRECATED int fullStackLinked( ADT *stack ); // 功能: 棧最大容量. // 參數: stack(棧對象的指針). // 返回: 棧最大容量. // 注意: 當 stack 爲NULL 時, 將錯誤退出程序. // 被棄用的函數. extern DEPRECATED int32_t capacityStackLinked( ADT *stack ); // 功能: 清空棧. // 參數: stack(棧對象的指針). // 返回: 無. // 注意: 當 stack 爲NULL 時, 將錯誤退出程序. extern void clearStackLinked( ADT *stack ); // 功能: 銷燬棧. // 參數: stack(存放棧對象的指針的指針). // 返回: 無. // 注意: 當 stack 爲NULL 時, 將錯誤退出程序. extern void delStackLinked( ADT **stack ); #undef ADT #endif
stackLinked.c
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include "stackLinked.h" // 功能: 打印錯誤信息後就錯誤退出程序. // 參數: expression(錯誤判斷表達式), message(需打印的錯誤信息). // 返回: 無. // 注意: 當expression爲真時,才觸發. #define ERROR_EXIT( expression, message ) \ if( (expression) ) { \ fprintf( stderr, "\nerror location: %s, %s, %u.\n", \ __FILE__, __func__, __LINE__ ); \ fprintf( stderr, "error message: %s.\n", \ !(message) ? __func__ : (message) ); \ exit( EXIT_FAILURE ); \ } #define MAX( a, b ) ((a) > (b) ? (a) : (b)) #define ADT StackLinked typedef struct NodeStackLinked { void *data; struct NodeStackLinked *next; } Node; struct StackLinked { int32_t size; Node *prev; // 指向棧底. Node *next; // 指向棧頂. }; ADT *newStackLinked( void ) { ADT *stack = NULL; stack = calloc( sizeof(*stack), 1 ); ERROR_EXIT( !stack, NULL ); return stack; } void *pushStackLinked( ADT *stack, void *data ) { Node *node = NULL; ERROR_EXIT( !stack, NULL ); node = malloc( sizeof(*node) ); ERROR_EXIT( !node, NULL ); node->data = data; node->next = stack->next; stack->prev = !stack->prev ? node : stack->prev; stack->next = node; ++stack->size; return data; } void *popStackLinked( ADT *stack ) { void *data = NULL; Node *node = NULL; ERROR_EXIT( !stack || stack->size < 1, NULL ); node = stack->next; stack->prev = node != stack->prev ? stack->prev : NULL; stack->next = node->next; --stack->size; data = node->data; free( node ); return data; } void *peekStackLinked( ADT *stack ) { ERROR_EXIT( !stack || stack->size < 1, NULL ); return stack->next->data; } void *peekBottomStackLinked( ADT *stack ) { ERROR_EXIT( !stack || stack->size < 1, NULL ); return stack->prev->data; } int existStackLinked( ADT *stack, void *data, CompareFunc *cmp ) { Node *n = NULL; ERROR_EXIT( !stack || !cmp, NULL ); for( n = stack->next; n != NULL; n = n->next ) { if( !cmp( n->data, data ) ) { return 1; } } return 0; } int32_t findStackLinked( ADT *stack, void *data, CompareFunc *cmp ) { Node *n = NULL; int32_t i = 0; ERROR_EXIT( !stack || !cmp, NULL ); for( n = stack->next; n != NULL; n = n->next ) { if( !cmp( n->data, data ) ) { return i; } ++i; } return -1; } int32_t findTailStackLinked( ADT *stack, void *data, CompareFunc *cmp ) { Node *p1 = NULL, *p2 = NULL, *p3 = NULL; int32_t ret = -1, i = 0; ERROR_EXIT( !stack || !cmp, NULL ); // 3指針法反轉鏈表. for( p1 = NULL, p2 = stack->next; p2 != NULL; p2 = p3 ) { p3 = p2->next; p2->next = p1; p1 = p2; } for( p3 = p1; p3 != NULL; p3 = p3->next ) { if( !cmp( p3->data, data ) ) { ret = i; break; } ++i; } // 3指針法再次反轉鏈表, 恢復原順序. for( p2 = p1, p1 = NULL; p2 != NULL; p2 = p3 ) { p3 = p2->next; p2->next = p1; p1 = p2; } return ret; } int32_t sizeStackLinked( ADT *stack ) { ERROR_EXIT( !stack, NULL ); return stack->size; } int emptyStackLinked( ADT *stack ) { ERROR_EXIT( !stack, NULL ); return stack->size < 1; } void reversalStackLinked( ADT *stack ) { Node *p1 = NULL, *p2 = NULL, *p3 = NULL; ERROR_EXIT( !stack, NULL ); stack->prev = stack->next; for( p1 = NULL, p2 = stack->next; p2 != NULL; p2 = p3 ) { // 三指針法反轉鏈表. p3 = p2->next; p2->next = p1; p1 = p2; } stack->next = p1; } int fullStackLinked( ADT *stack ) { ERROR_EXIT( !stack, NULL ); return 0; } int32_t capacityStackLinked( ADT *stack ) { ERROR_EXIT( !stack, NULL ); return INT32_MAX; } void clearStackLinked( ADT *stack ) { Node *current = NULL, *next = NULL; ERROR_EXIT( !stack, NULL ); for( current = stack->next; current != NULL; current = next ) { next = current->next; free( current ); } stack->size = 0; } void delStackLinked( ADT **stack ) { Node *current = NULL, *next = NULL; ERROR_EXIT( !stack, NULL ); if( !stack ) { return; } for( current = stack[0]->next; current != NULL; current = next ) { next = current->next; free( current ); } free( *stack ); *stack = NULL; }
stackLinkedTest.c
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <time.h> #include "stackLinked.h" // a>b返回正數, a<b返回負數, 不然返回0. static int cmp( const void *a, const void *b ) { return *(int32_t *) a - *(int32_t *) b; } int main( int argc, char *argv[] ) { char *tf[] = {"false", "true"}; int32_t *a = NULL, n = 0; int32_t i = 0, k = 0; StackLinked *s = NULL; srand( time( NULL ) ); printf( "please input array length: n = " ); scanf( "%d%*c", &n ); printf( "\n" ); a = malloc( sizeof(*a) * n ); for( i = 0; i < n; ++i ) { a[i] = rand() % 322; //a[i] = 1; } printf( "&s = %p, s = %p\n", &s, s ); s = newStackLinked(); printf( "new: &s = %p, s = %p\n", &s, s ); printf( "peek = %d\n", emptyStackLinked( s ) ? INT32_MIN : *(int32_t *) peekStackLinked( s ) ); printf( "peekBottom = %d\n", emptyStackLinked( s ) ? INT32_MIN : *(int32_t *) peekBottomStackLinked( s ) ); printf( "size = %d\n", sizeStackLinked( s ) ); printf( "empty = %s\n", tf[emptyStackLinked( s )]); printf( "\n" ); for( i = 0; i < n; ++i ) { printf( "push: %4d\n", *(int32_t *) pushStackLinked( s, &a[i] ) ); } printf( "\n" ); printf( "peek = %d\n", emptyStackLinked( s ) ? INT32_MIN : *(int32_t *) peekStackLinked( s ) ); printf( "peekBottom = %d\n", emptyStackLinked( s ) ? INT32_MIN : *(int32_t *) peekBottomStackLinked( s ) ); printf( "size = %d\n", sizeStackLinked( s ) ); printf( "empty = %s\n", tf[emptyStackLinked( s )] ); printf( "\n" ); //k = a[0]; k = rand(); printf( "exist &k(%d) = %s\n", k, tf[existStackLinked( s, &k, cmp )] ); printf( "\n" ); k = a[0]; //k = rand(); printf( "find &k(%d) = %d\n", k, findStackLinked( s, &k, cmp ) ); printf( "\n" ); //k = a[0]; k = rand(); printf( "findTile &k(%d) = %d\n", k, findTailStackLinked( s, &k, cmp ) ); printf( "\n" ); //reversalStackLinked( s ); // 反轉棧. while( !emptyStackLinked( s ) ) { printf( "pop: %4d\n", *(int32_t *) popStackLinked( s ) ); } printf( "\n" ); printf( "peek = %d\n", emptyStackLinked( s ) ? INT32_MIN : *(int32_t *) peekStackLinked( s ) ); printf( "peekBottom = %d\n", emptyStackLinked( s ) ? INT32_MIN : *(int32_t *) peekBottomStackLinked( s ) ); printf( "size = %d\n", sizeStackLinked( s ) ); printf( "empty = %s\n", tf[emptyStackLinked( s )] ); printf( "\n" ); delStackLinked( &s ); printf( "del: &s = %p, s = %p\n", &s, s ); return EXIT_SUCCESS; }