栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

[C基础]栈、单向链表和队列的简易C实现

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

[C基础]栈、单向链表和队列的简易C实现

C语言比较偏底层,很多常用的数据结构需要自己实现,不像高等语言直接就有现成的类库可使用。

1. 栈定义和实现

下面是一个栈的简易实现,适合新人入门参考。可以方便的对任意数据类型进行压栈出栈操作。

#define MAX_STACK_DEPTH 4096

typedef struct _STACK
{
    void *Array[MAX_STACK_DEPTH];
    int  Depth;
    void (*Push)(struct _STACK *,void *);
    void *(*Pop)(struct _STACK *);
}
STACK;

void StackPush(STACK *Stack, void *Element)
{
    if (Stack->Depth < MAX_STACK_DEPTH)
    {
        Stack->Array[Stack->Depth++] = Element;
    }
}

void *StackPop(STACK *Stack)
{
    if (Stack->Depth <= 0)
    {
        return NULL;
    }

    return Stack->Array[--Stack->Depth];
}

注意:

为了简单,我们没有考虑栈溢出情况。如果使用环境可能存在压栈溢出。我们需要改进StackPush函数,增加溢出判断。

int StackPush(STACK *Stack, void *Element)
{
    if (Stack->Depth >= MAX_STACK_DEPTH)
    {
        return -1;
    }

    Stack->Array[Stack->Depth++] = Element;
    return 0;
}
2. 单向链表定义和实现

单向链表在实际使用中非常常见,下面是其定义和实现,包含了用来验证的创建、释放、打印函数。

typedef struct _NODE
{
    struct _NODE *Next;
    int Value;
}
NODE;

void ListPrint(NODE *Head)
{
    while (Head)
    {
        printf("%d ", Head->Value);
        Head = Head->Next;
    }
    printf("n");
}

void ListFree(NODE *Head)
{
    NODE *tmp = NULL;
    while (Head)
    {
        tmp = Head->Next;
        free(Head);
        Head = tmp;
    }
}

NODE *ListCreate(void)
{
    NODE *head = NULL, *lastNode = NULL, *curNode = NULL;
    int val = 0;

    printf("please input space-separated elements:n");
    while (scanf("%d", &val) != EOF)
    {
        curNode = (NODE *)malloc(sizeof(NODE));
        if (curNode == NULL)
        {
            return head;    
        }
        curNode->Value = val;
        curNode->Next = NULL;

        if (head == NULL)
        {
            head = curNode;
        }

        if (lastNode == NULL)
        {
            lastNode = curNode;
        }
        else
        {
            lastNode->Next = curNode;
            lastNode = curNode;
        }
        
        if (getchar() == 'n')
        {
            break;
        }
    }

    return head;
}

栈和链表综合使用示例--单向链表的反转:

通常我们使用多个指针逐步实现链表反转,但是栈天生就具备反转特性,所以使用栈来实现更简洁一些。

NODE *ListReverse(NODE *Head)
{
    NODE *curNode = NULL;
    STACK stack = {.Depth = 0, .Push = StackPush, .Pop = StackPop};

    if (Head == NULL)
    {
        return NULL;
    }

    while (Head)
    {
        stack.Push(&stack, (void *)Head);
        Head = Head->Next;
    }

    Head = (NODE *)stack.Pop(&stack);
    curNode = Head;
    while (stack.Depth > 0)
    {
        curNode->Next = (NODE *)stack.Pop(&stack);
        curNode = curNode->Next;
    }
    curNode->Next = NULL;
    
    return Head;
}

完整示例代码:

#include 
#include 
#include 

#define MAX_STACK_DEPTH 4096

typedef struct _STACK
{
    void *Array[MAX_STACK_DEPTH];
    int  Depth;
    void (*Push)(struct _STACK *,void *);
    void *(*Pop)(struct _STACK *);
}
STACK;

void StackPush(STACK *Stack, void *Element)
{
    if (Stack->Depth < MAX_STACK_DEPTH)
    {
        Stack->Array[Stack->Depth++] = Element;
    }
}

void *StackPop(STACK *Stack)
{
    if (Stack->Depth <= 0)
    {
        return NULL;
    }

    return Stack->Array[--Stack->Depth];
}

typedef struct _NODE
{
    struct _NODE *Next;
    int Value;
}
NODE;

void ListPrint(NODE *Head)
{
    while (Head)
    {
        printf("%d ", Head->Value);
        Head = Head->Next;
    }
    printf("n");
}

void ListFree(NODE *Head)
{
    NODE *tmp = NULL;
    while (Head)
    {
        tmp = Head->Next;
        free(Head);
        Head = tmp;
    }
}

NODE *ListCreate(void)
{
    NODE *head = NULL, *lastNode = NULL, *curNode = NULL;
    int val = 0;

    printf("please input space-separated elements:n");
    while (scanf("%d", &val) != EOF)
    {
        curNode = (NODE *)malloc(sizeof(NODE));
        if (curNode == NULL)
        {
            return head;    
        }
        curNode->Value = val;
        curNode->Next = NULL;

        if (head == NULL)
        {
            head = curNode;
        }

        if (lastNode == NULL)
        {
            lastNode = curNode;
        }
        else
        {
            lastNode->Next = curNode;
            lastNode = curNode;
        }
        
        if (getchar() == 'n')
        {
            break;
        }
    }

    return head;
}

NODE *ListReverse(NODE *Head)
{
    NODE *curNode = NULL;
    STACK stack = {.Depth = 0, .Push = StackPush, .Pop = StackPop};

    if (Head == NULL)
    {
        return NULL;
    }

    while (Head)
    {
        stack.Push(&stack, (void *)Head);
        Head = Head->Next;
    }

    Head = (NODE *)stack.Pop(&stack);
    curNode = Head;
    while (stack.Depth > 0)
    {
        curNode->Next = (NODE *)stack.Pop(&stack);
        curNode = curNode->Next;
    }
    curNode->Next = NULL;
    
    return Head;
}

int main(int argc, char *argv[])
{
   NODE *list = NULL;

   list = ListCreate();
   ListPrint(list);
   list = ListReverse(list);
   ListPrint(list);
   ListFree(list);
   return 0;
}
3. 队列定义和实现

下面是一个队列的建议实现,遵循先进先出原则,从队头Pop弹出元素,从队尾Push压入元素。

#define MAX_QUEUE_LENGTH 4096

typedef struct _QUEUE
{
    void *Array[MAX_QUEUE_LENGTH];
    int Length;
    int Head;
    int Tail;
    void (*Push)(struct _QUEUE *, void *);
    void *(*Pop)(struct _QUEUE *);
}
QUEUE;

void QueuePush(QUEUE *Queue, void *Element)
{
    if (Queue->Length >= MAX_QUEUE_LENGTH)
    {
        return;
    }

    Queue->Array[Queue->Tail] = Element;
    if (Queue->Tail < MAX_QUEUE_LENGTH - 1)
    {
        Queue->Tail++;
    }
    else
    {
        Queue->Tail = 0;
    }
    Queue->Length++;
}

void *QueuePop(QUEUE *Queue)
{
    void *ele = NULL;

    if (Queue->Length <= 0)
    {
        return NULL;
    }

    ele = Queue->Array[Queue->Head];
    if (Queue->Head < MAX_QUEUE_LENGTH - 1)
    {
        Queue->Head++;
    }
    else
    {
        Queue->Head = 0;
    }
    Queue->Length--;

    return ele;
}


注意:

为了简单,我们没有考虑队列溢出情况。如果使用环境可能存在队列溢出。我们需要改进QueuePush函数,增加溢出判断。

int QueuePush(QUEUE *Queue, void *Element)
{
    if (Queue->Length >= MAX_QUEUE_LENGTH)
    {
        return -1;
    }

    Queue->Array[Queue->Tail] = Element;
    if (Queue->Tail < MAX_QUEUE_LENGTH - 1)
    {
        Queue->Tail++;
    }
    else
    {
        Queue->Tail = 0;
    }
    Queue->Length++;
    return 0;
}

队列和栈的示例--两个队列实现栈:

typedef struct _QUEUE_STACK
{
    QUEUE Queue1;
    QUEUE Queue2;
}
QUEUE_STACK;

int QueueStackDepth(QUEUE_STACK *Stack)
{
    if (Stack->Queue1.Length == 0 && Stack->Queue2.Length == 0)
    {
        return 0;
    }
    else if (Stack->Queue1.Length == 0)
    {
        return Stack->Queue2.Length;
    }
    else
    {
        return Stack->Queue1.Length;
    }
}

void QueueStackPush(QUEUE_STACK *Stack, void *Element)
{
    if (Stack->Queue1.Length > 0)
    {
        Stack->Queue1.Push(&Stack->Queue1, Element);
    }
    else
    {
        Stack->Queue2.Push(&Stack->Queue2, Element);
    }
}

void *QueueStackPop(QUEUE_STACK *Stack)
{
    QUEUE *popQueue = NULL, *pushQueue = NULL;
    void *ele = NULL;
    
    if (Stack->Queue1.Length == 0 && Stack->Queue2.Length == 0)
    {
        return NULL;
    }
    else if (Stack->Queue1.Length == 0)
    {
        pushQueue = &Stack->Queue1;
        popQueue = &Stack->Queue2;
    }
    else
    {
        pushQueue = &Stack->Queue2;
        popQueue = &Stack->Queue1;  
    }
    
    while (popQueue->Length > 1)
    {
        ele = popQueue->Pop(popQueue);
        pushQueue->Push(pushQueue, ele)
    }

    return popQueue->Pop(popQueue);
}

完整示例代码如下,直接gcc编译执行:

#include 
#include 
#include 

#define MAX_QUEUE_LENGTH 4096

typedef struct _QUEUE
{
    void *Array[MAX_QUEUE_LENGTH];
    int Length;
    int Head;
    int Tail;
    void (*Push)(struct _QUEUE *, void *);
    void *(*Pop)(struct _QUEUE *);
}
QUEUE;

void QueuePush(QUEUE *Queue, void *Element)
{
    if (Queue->Length >= MAX_QUEUE_LENGTH)
    {
        return;
    }

    Queue->Array[Queue->Tail] = Element;
    if (Queue->Tail < MAX_QUEUE_LENGTH - 1)
    {
        Queue->Tail++;
    }
    else
    {
        Queue->Tail = 0;
    }
    Queue->Length++;
}

void *QueuePop(QUEUE *Queue)
{
    void *ele = NULL;

    if (Queue->Length <= 0)
    {
        return NULL;
    }

    ele = Queue->Array[Queue->Head];
    if (Queue->Head < MAX_QUEUE_LENGTH - 1)
    {
        Queue->Head++;
    }
    else
    {
        Queue->Head = 0;
    }
    Queue->Length--;

    return ele;
}

typedef struct _QUEUE_STACK
{
    QUEUE Queue1;
    QUEUE Queue2;
}
QUEUE_STACK;

int QueueStackDepth(QUEUE_STACK *Stack)
{
    if (Stack->Queue1.Length == 0 && Stack->Queue2.Length == 0)
    {
        return 0;
    }
    else if (Stack->Queue1.Length == 0)
    {
        return Stack->Queue2.Length;
    }
    else
    {
        return Stack->Queue1.Length;
    }
}

void QueueStackPush(QUEUE_STACK *Stack, void *Element)
{
    if (Stack->Queue1.Length > 0)
    {
        Stack->Queue1.Push(&Stack->Queue1, Element);
    }
    else
    {
        Stack->Queue2.Push(&Stack->Queue2, Element);
    }
}

void *QueueStackPop(QUEUE_STACK *Stack)
{
    QUEUE *popQueue = NULL, *pushQueue = NULL;
    void *ele = NULL;

    if (Stack->Queue1.Length == 0 && Stack->Queue2.Length == 0)
    {
        return NULL;
    }
    else if (Stack->Queue1.Length == 0)
    {
        pushQueue = &Stack->Queue1;
        popQueue = &Stack->Queue2;
    }
    else
    {
        pushQueue = &Stack->Queue2;
        popQueue = &Stack->Queue1;
    }

    while (popQueue->Length > 1)
    {
        ele = popQueue->Pop(popQueue);
        pushQueue->Push(pushQueue, ele);
    }

    return popQueue->Pop(popQueue);
}

int main(int argc, char *argv[])
{
    QUEUE_STACK stack;
    int val = 0;

    stack.Queue1.Push = QueuePush;
    stack.Queue1.Pop = QueuePop;
    stack.Queue1.Length  = stack.Queue1.Head = stack.Queue1.Tail = 0;

    stack.Queue2.Push = QueuePush;
    stack.Queue2.Pop = QueuePop;
    stack.Queue2.Length  = stack.Queue2.Head = stack.Queue2.Tail = 0;

    printf("please input space-separated elements:n")
    while (scanf("%d", &val) != EOF)
    {
        QueueStackPush(&stack, (void *)val);

        if (getchar() == 'n')
        {
            break;
        }
    }

    while (QueueStackDepth(&stack) > 0)
    {
        val = (int)QueueStackPop(&stack);
        printf("%d ", val);
    }
    printf("n");

    return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/779330.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号