您当前的位置: 首页 >  链表

Jave.Lin

暂无认证

  • 3浏览

    0关注

    704博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

C - 单链表倒序遍历

Jave.Lin 发布时间:2020-04-30 00:13:55 ,浏览量:3

思路:

利用函数栈的 后进先出 的特性

如果链表太深,会爆掉函数栈的

// jave.lin 2020.4.30
#include 
#include 

typedef struct LL LinkedList;
typedef struct stack Stack;

#define GET_LL(address) ((LinkedList*)(((void*)0)+address))
#define GET_PTR(offset) (NULL+offset)
#define GET_TYPE_PTR(offset,type) ((type)(NULL+offset))

typedef struct LL {
    int value;
    LinkedList* next;
} LinkedList;

typedef struct stack {
    size_t size;
    int pos;
    int* address;
} Stack;

size_t GetLLSize(LinkedList* ll) {
    size_t ret = 0;
    while(ll != NULL) {
        ++ret;
        ll = ll->next;
    }
    return ret;
}

Stack* MallocStack(size_t size) {
    Stack* ret = (Stack*)(malloc(sizeof(Stack)));
    if (ret == NULL) return NULL;
    ret->pos = -1;
    ret->size = size;
    ret->address = malloc(sizeof(int) * size);
    if (ret->address == NULL) {
        free(ret);
        return NULL;
    }
    return ret;
}
int IsEmptyStack(Stack* stack) {
    return (stack->pos == -1) ? 1 : 0;
}
int IsFullStack(Stack* stack) {
    return (stack->pos == stack->size - 1) ? 1 : 0;
}
void FreeStack(Stack* stack) {
    free(stack->address);
    free(stack);
}
int PushStack(Stack* stack, void* ptr) {
    if (IsFullStack(stack) == 1) return 0;
    *(stack->address + (++stack->pos)) = (int)ptr;
    return 1;
}
void* PopStack(Stack* stack) {
    if (IsEmptyStack(stack) == 1) return NULL;
    return (void*)(*(stack->address + (stack->pos--)));
}
void StackIterate(Stack* stack, void (* cb)(void*)) {
    while(!IsEmptyStack(stack)) {
        cb(PopStack(stack));
    }
}

// 根据递归来倒序遍历
void ReverseIterate(LinkedList* ll, void (* cb)(LinkedList*)) {
    if (ll == NULL) return;

    if (ll->next != NULL) {
        ReverseIterate(ll->next, cb);
        cb(ll);
    } else {
        cb(ll);
    }
}

// 根据数组来逆序,但是没什么实用性,因为链表是变长与可不连续而设计的
// 但是数组是定长,与连续内存特性的,resize array来变长数组效率不高
// 而且resize后,如果是插入中间数据,则需要将后续数据遍历挪到
// 链表与数组各有优缺点:
// 数组:
//      优点:连续紧凑内存,而减少内存用量
//      缺点:定长,不方便插入、删除数据
// 链表:
//      优点:变长,灵活插入、删除
//      缺点:需要多一份指针地址内存
void ReverseIterate1(LinkedList* ll, void (* cb)(LinkedList*)) {
    
    if (ll == NULL) return;

    size_t size = GetLLSize(ll);
    int arr[size];

    for (size_t i = 0; i next;
    }

    for (size_t i = 0; i address + stack->pos), 
        //     (int)ll,
        //     (stack->address + stack->pos));
        ll = ll->next;
    }

    // StackIterate(stack, ) // 回调不一样的签名没啥用,虽然还可以再套一层callback来处理这里的cb回调,但没必要了
    while(IsEmptyStack(stack) != 1) { // 还是直接遍历吧
        cb((LinkedList*)PopStack(stack));
    }

    FreeStack(stack);
}

void printNode(LinkedList* node) {
    printf("%d,", node->value);
}

void freeNde(LinkedList* node) {
    free(node);
}

int main() {

    LinkedList* header = malloc(sizeof(LinkedList));
    header->value = -1;

    // construct & input value
    LinkedList* p = header;
    printf("initialize : %d,", p->value);
    for (size_t i = 0; i next = malloc(sizeof(LinkedList));
        p->next->value = i;
        printf("%d,", i);
        p = p->next;
    }
    p->next = NULL;
    printf("\n");

    // 倒序遍历:递归
    printf("reverse iterate linked list by [recursion]:\n");
    ReverseIterate(header, printNode);
    printf("\n");
    // 倒序遍历:数组
    printf("reverse iterate linked list by [array]:\n");
    ReverseIterate1(header, printNode);
    printf("\n");
    // 倒序遍历:栈
    printf("reverse iterate linked list by [stack]:\n");
    ReverseIterate2(header, printNode);
    printf("\n");

    // 总结为:可以使用多种多样的方式来倒序遍历
    // 只要某个数据结构可以支持遍历就好了

    printf("positive iterate linked list:\n");
    p = header;
    while(p != NULL) {
        printf("%d,", p->value);
        p = p->next;
    }

    printf("\n");
    // 倒序遍历
    ReverseIterate(header, freeNde);

    printf("done!\n");
    return 0;
}

输出

initialize : -1,0,1,2,3,4,5,6,7,8,9,
reverse iterate linked list by [recursion]:
9,8,7,6,5,4,3,2,1,0,-1,
reverse iterate linked list by [array]:
9,8,7,6,5,4,3,2,1,0,-1,
reverse iterate linked list by [stack]:
9,8,7,6,5,4,3,2,1,0,-1,
positive iterate linked list:
-1,0,1,2,3,4,5,6,7,8,9,
done!
总结

可以使用多种多样的方式来倒序遍历 只要某个数据结构可以支持遍历就好了

References
  • 单链表的逆序遍历函数
关注
打赏
1664331872
查看更多评论
立即登录/注册

微信扫码登录

0.0467s