【c语言】 单链表

单链表,顾名思义是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素

链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

我们在这里使用C语言实现:

.h 文件:

#pragma once
#include<assert.h>
#include <malloc.h>

typedef int DataType;

typedef struct SListNode
{
    DataType data;
    struct SListNode* next;
}SListNode;

void PushBack(SListNode* & pHead, DataType x);
void PopBack(SListNode* & pHead);
void PushFront(SListNode* & pHead, DataType x);
void PopFront(SListNode* & pHead);
SListNode* Find(SListNode* pHead, DataType x);
void Insert(SListNode* pos, DataType x);
void Erase(SListNode* pos);
void DestoryList(SListNode*& pHead);

void DestoryList(SListNode*& pHead)
{
    SListNode* cur = pHead;
    while (cur)
    {
        SListNode* tmp =  cur;
        cur = cur->next;
        free(tmp);
    }

    pHead = NULL;
}

SListNode* _BuyNode(DataType x)
{
    SListNode* tmp = (SListNode*)malloc(sizeof(SListNode));
    tmp->data = x;
    tmp->next = NULL;

    return tmp;
}

void PrintSlist(SListNode* pHead)
{
    SListNode* cur = pHead;
    while (cur)
    {
        printf("%d->",cur->data);
        cur = cur->next;
    }

    printf("NULL\n");
}

//void PushBack(SListNode** ppHead, DataType x)
//{
//    assert(ppHead);
//
//    // 1.空
//    // 2.不为空
//    if(*ppHead == NULL)
//    {
//        *ppHead = _BuyNode(x);
//    }
//    else
//    {
//        // 找尾
//        SListNode* tail = *ppHead;
//        while(tail->next != NULL)
//        {
//            tail = tail->next;
//        }
//
//        tail->next = _BuyNode(x);
//    }
//}

void PushBack(SListNode* & pHead, DataType x)
{
    // 1.空
    // 2.不为空
    if(pHead == NULL)
    {
        pHead = _BuyNode(x);
    }
    else
    {
        // 找尾
        SListNode* tail = pHead;
        while(tail->next != NULL)
        {
            tail = tail->next;
        }

        tail->next = _BuyNode(x);
    }
}

void PopBack(SListNode* & pHead)
{
    //
    // 1.空
    // 2.一个节点
    // 3.多个节点
    //
    if(pHead == NULL)
    {
        return;
    }
    else if(pHead->next == NULL)
    {
        free(pHead);
        pHead = NULL;
    }
    else
    {
        SListNode* tail = pHead;
        SListNode* prev = NULL;
        while (tail->next)
        {
            prev = tail;
            tail = tail->next;
        }

        free(tail);
        prev->next = NULL;
    }
}

void PushFront(SListNode* & pHead, DataType x)
{
    // 1.空
    // 2.不空
    if(pHead == NULL)
    {
        pHead = _BuyNode(x);
    }
    else
    {
        SListNode* tmp = _BuyNode(x);
        tmp->next = pHead;
        pHead = tmp;
    }
}

void PopFront(SListNode*& pHead)
{
    //
    // 1.空
    // 2.一个节点
    // 3.一个以上的节点
    //
    if(pHead == NULL)
    {
        return;
    }
    else if(pHead->next == NULL)
    {
        free(pHead);
        pHead = NULL;
    }
    else
    {
        SListNode* tmp = pHead;
        pHead = pHead->next;

        free(tmp);
    }
}

SListNode* Find(SListNode* pHead, DataType x)
{
    SListNode* cur = pHead;
    while (cur)
    {
        if (cur->data == x)
        {
            return cur;
        }

        cur = cur->next;
    }

    return NULL;
}

void Insert(SListNode* pos, DataType x)
{
    assert(pos);
    
    //SListNode* tmp = _BuyNode(x);
    //SListNode* next = pos->next;
    //pos->next = tmp;
    //tmp->next = next;

    SListNode* tmp = _BuyNode(x);
    tmp->next = pos->next;
    pos->next = tmp;

}

void Erase(SListNode*& pHead, SListNode* pos)
{
    assert(pos);
    assert(pHead);

    if (pHead == pos)
    {
        pHead = pHead->next;
        free(pos);
        return;
    }

    SListNode* prev = pHead;
    while (prev)
    {
        if (prev->next == pos)
        {
            prev->next = pos->next;
            free(pos);
            break;
        }

        prev = prev->next;
    }
}

/////////////////////////////////////////////////
// 删除一个无头单链表的非尾节点
void DelNonTailNode(SListNode* pos)
{
    assert(pos);
    assert(pos->next);

    SListNode* del = pos->next;
    SListNode* next = del->next;

    pos->data = del->data;
    pos->next = next;
    free(del);
}

// 在无头单链表的一个非头节点前插入一个节点
void InsertFrontNode(SListNode* pos, DataType x)
{
    assert(pos);

    //SListNode* tmp = _BuyNode(x);
    //tmp->next = pos->next;
    //pos->next = tmp;

    //DataType tmpData = pos->data;
    //pos->data = tmp->data;
    //tmp->data = tmpData;

    SListNode* tmp = _BuyNode(pos->data);
    tmp->next = pos->next;
    pos->next = tmp;
    pos->data = x;
}

//struct Ret
//{    
//    SListNode* first;
//    SListNode* second;
//};

SListNode* FindMidNode(SListNode* pHead)
{
    SListNode* fast = pHead;
    SListNode* slow = pHead;

    while (fast&&fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
    }

    //while (fast)
    //{
    //    if (fast->next)
    //    {
    //        fast = fast->next->next;
    //    }
    //    else
    //    {
    //        break;
    //    }

    //    slow = slow->next;
    //}

    return slow;
}

SListNode* FindKNode(SListNode* pHead, int k)
{
    SListNode* fast = pHead;
    SListNode* slow = pHead;

    while (fast && k--)
    {
        fast = fast->next;
    }

    if (k > 0)
        return NULL;

    while (fast)
    {
        slow = slow->next;
        fast = fast->next;
    }

    return slow;
}

void PrintTailToHead(SListNode* pHead)
{
    if (pHead)
    {
        PrintTailToHead(pHead->next);
        printf("%d ", pHead->data);
    }
}

SListNode* Reverse(SListNode* pHead)
{
    SListNode* cur = pHead;
    SListNode* newHead = NULL;

    while(cur)
    {
        SListNode* tmp = cur;
        cur = cur->next;

        tmp->next = newHead;
        newHead = tmp;
    }

    return newHead;
}

.cpp 文件:

#include <stdio.h>

#include "SList.h"

// PushBack/PopBack
void Test1()
{
    SListNode* list = NULL;
    PushBack(list, 1);
    PushBack(list, 2);
    PushBack(list, 3);
    PushBack(list, 4);

    PrintSlist(list);

    PopBack(list);
    PopBack(list);
    PopBack(list);
    PopBack(list);
    PopBack(list);

    PrintSlist(list);
}

// PushFront/PopFront
void Test2()
{
    SListNode* list = NULL;
    PushFront(list, 1);
    PushFront(list, 2);
    PushFront(list, 3);
    PushFront(list, 4);
    PrintSlist(list);

    PopFront(list);
    PopFront(list);
    PopFront(list);
    PopFront(list);
    PopFront(list);

    PrintSlist(list);
}

// Find/Insert
void Test3()
{
    SListNode* list = NULL;
    PushFront(list, 1);
    PushFront(list, 2);
    PushFront(list, 3);
    PushFront(list, 4);
    PrintSlist(list);

    SListNode* pos = Find(list, 3);
    Insert(pos, 10);

    pos = Find(list, 1);
    Insert(pos, 100);

    PrintSlist(list);

    // ??
    pos = Find(list, 4);
    Erase(list, pos);

    pos = Find(list, 100);
    Erase(list, pos);

    pos = Find(list, 3);
    Erase(list, pos);

    PrintSlist(list);
}

//DelNonTailNode
void Test4()
{
    SListNode* list = NULL;
    PushBack(list, 1);
    PushBack(list, 2);
    PushBack(list, 3);
    PushBack(list, 4);

    PrintSlist(list);

    SListNode* pos = list;
    DelNonTailNode(pos);

    PrintSlist(list);
}

void Test5()
{
    SListNode* list = NULL;
    PushBack(list, 1);

    SListNode* pos = FindMidNode(list);
    printf("%d\n", pos->data);

    PushBack(list, 2);
    PushBack(list, 3);
    PushBack(list, 4);

    pos = FindMidNode(list);
    printf("%d\n", pos->data);

    pos = FindKNode(list, 4);
    pos = FindKNode(list, 100);
}

void Test6()
{
    SListNode* list = NULL;
    PushBack(list, 1);
    PushBack(list, 2);
    PushBack(list, 3);
    PushBack(list, 4);

    //PrintTailToHead(list);

    list = Reverse(list);
    PrintSlist(list);

    //PrintTailToHead(list);
}

void Test7()
{
    SListNode* list = NULL;
    PushBack(list, 1);
    PushBack(list, 2);
    PushBack(list, 3);
    PushBack(list, 4);
    PushBack(list, 5);
    PushBack(list, 6);
    PushBack(list, 7);

    SListNode* tail = Find(list, 7);
    tail->next = list;

    SListNode* lastOne = JoseCycle(list, 3);
    printf("幸存者:%d\n", lastOne->data);
}

void Test8()
{
    SListNode* list = NULL;
    PushBack(list, 3);
    PushBack(list, 2);
    PushBack(list, 3);
    PushBack(list, 6);
    PushBack(list, 0);
    PushBack(list, 9);
    PushBack(list, 7);
    PrintSlist(list);

    BubbleSort(list);
    PrintSlist(list);
}

void Test9()
{
    SListNode* list1 = NULL, *list2 = NULL;
    PushBack(list1, 2);
    PushBack(list1, 3);
    PushBack(list1, 8);
    PrintSlist(list1);

    PushBack(list2, 1);
    PushBack(list2, 3);
    PushBack(list2, 5);
    PushBack(list2, 7);
    PrintSlist(list2);

    SListNode* list = MergeList(list1, list2);
    PrintSlist(list);

    DestoryList(list);
}

void Test10()
{
    SListNode* list = NULL;
    PushBack(list, 1);
    PushBack(list, 2);
    PushBack(list, 3);
    PushBack(list, 4);
    PushBack(list, 5);
    PushBack(list, 6);
    PushBack(list, 7);
    PrintSlist(list);

    SListNode* tail = Find(list, 7);
    SListNode* enrtyNode = Find(list, 4);
    tail->next = enrtyNode;

    SListNode* meetNode = CheckCycle(list);
    int length = GetCycleLength(meetNode);
    printf("meetNode:%d, length:%d\n", meetNode->data, length);

    SListNode* retEntryNode = GetEntryNode(list);
    //assert(retEntryNode == enrtyNode);
}

int main()
{
    //Test1();
    //Test2();
    //Test3();
    //Test4();
    //Test5();
    //Test6();
    //Test7();
    //Test8();
    //Test9();

    Test10();

    return 0;
}
时间: 2024-08-02 11:00:45

【c语言】 单链表的相关文章

(转载)C语言单链表实现19个功能完全详解

最近在复习数据结构,想把数据结构里面涉及的都自己实现一下,完全是用C语言实现的. 自己编写的不是很好,大家可以参考,有错误希望帮忙指正,现在正处于编写阶段,一共将要实现19个功能.到目前我只写了一半,先传上来,大家有兴趣的可以帮忙指正,谢谢 在vs2010上面编译运行无错误. 每天都会把我写的新代码添加到这个里面.直到此链表完成. #include "stdafx.h" #include "stdio.h" #include <stdlib.h> #in

[c语言]单链表的实现

一.基础知识:链表(线性表的链式存储结构) (1)特点:逻辑关系相邻,物理位置不一定相邻. (2)分类: a.不带头节点 b.带头节点 (3)单链表的存储结构: typedef struct SListNode {  DataType data;  struct SListNode* next; }SListNode; 二.代码实现(因避开使用二级指针,所以代码中使用了c++中的引用):此处构造的为不带头节点的链表 (1)sList.h   #pragma once typedef int Da

c语言-单链表(二)

继续复习链表知识点,本章包含单链表的增加,删除,判断是否为空,和链表长度,以及链表的排序 几个知识点 1.链表的判断是否为空 //1.判断链表是否为空 bool isempty_list(PNODE pHead) { return pHead->pNext == NULL; } 2. 计算链表的长度 //2.链表长度 int length_list(PNODE pHead) { PNODE pFirst = pHead->pNext;//获取头结点 int num = 0; while (pF

c语言单链表实现

/************************************************************************* > File Name: singleLineTable.c > Author: zshh0604 > Mail: [email protected] > Created Time: 2014年10月15日 星期三 11时34分08秒 **************************************************

C语言单链表

学过线性表中的顺序表的都知道,顺序表里的数据在物理内存上是相邻的,所以当我们在顺序表中想要访问下一个元素时可以直接去访问,就像数组一样.但是单链表却不同,单链表的数据存储的位置是动态分配的,也就是说单链表的存储在物理内存上不是相邻的,所以我们就只能通过指针这种方式来把单链表串起来,通过指针来访问下一个结点. 单链表结点 单链表的结点里有数据域和指针域,数据域是用来储存数据的,指针域是用来储存直接后继结点的域. typedef struct Node{ int data;//数据域 struct

C语言单链表实现19个功能完全详解

#include "stdafx.h" #include "stdio.h" #include <stdlib.h> #include "string.h" typedef int elemType ; /************************************************************************/ /* 以下是关于线性表链接存储(单链表)操作的18种算法 */ /* 1.初始化线性

C语言单链表逆置的代码实现 (简单易懂版)

嗯,,这是自己写的第一篇博客哈,写的不好大家不要见怪,主要是想把自己的一些思想分享给大家.也欢迎大家指出错误,一同进步. 话不多说,直接先说想法.要把一个单链表逆置,可以大致分为下列几步.先创建一个链表.然后要考虑到链表的逆置实现.最后是链表的输出.有了这样过几步大概的想法之后,我们便要来一步步的实现啦.嗯,,创建链表就不说了,大家都会.  然后呢就是链表的逆置,这里我是采用的就地逆置法,,嗯,反正我是这么叫的,大家可以参考一下.当然啦,你得考虑到函数的形参和返回值以及指针的交接,这里如果出了问

c语言-单链表(一)

定义节点: typedef struct Node { int data; Node* pNext; }NODE, *PNODE; 细节说明,PNode 就代表struct Node* ,上面的表单是也可以写成如下形式,含义是一样的 typedef struct Node { int data; Node* pNext; }*PNODE,NODE ; 算法操作 1. 创建链表 //1.初始化链表 PNODE create_list(void) { int len,val; printf("%s&

C语言实现单链表节点的删除(带头结点)

我在之前一篇博客<C语言实现单链表节点的删除(不带头结点)>中具体实现了怎样在一个不带头结点的单链表的删除一个节点,在这一篇博客中我改成了带头结点的单链表.代码演示样例上传至 https://github.com/chenyufeng1991/DeleteLinkedList_HeadNode.删除类型有两种: (1)删除某个位置pos的节点: (2)推断x值是否在链表中,若存在则删除该节点: 核心代码例如以下: //删除某个位置pos的节点 Node *DeletePosNode(Node

「C语言」单链表/双向链表的建立/遍历/插入/删除

最近临近期末的C语言课程设计比平时练习作业一下难了不止一个档次,第一次接触到了C语言的框架开发,了解了View(界面层).Service(业务逻辑层).Persistence(持久化层)的分离和耦合,一种面向过程的MVC的感觉. 而这一切的基础就在于对链表的创建.删除.输出.写入文件.从文件读出...... 本篇文章在于巩固链表的基础知识(整理自<C语言程序设计教程--人民邮电出版社>第十章),只对链表的概念及增删改查作出探讨,欢迎指教. 一.链表结构和静态/动态链表 二.单链表的建立与遍历