zoukankan      html  css  js  c++  java
  • 单链表的基本操作实现

     
    写这篇博文的原因
     
    C语言有三个重要部分:流程控制、函数、指针。对于指针,单单了解它的简单运用是远远不够的,最重要的是学习链表。所以这篇文章通过用C语言实现链表的一些基本操作和总结,希望对C语言的指针有更新的理解和认识。
     
    单链表的定义
     
    单链表是通过一组任意的存储单元来存储线性表中的数据元素,这些存储单元可以是连续的也可以是不连续的。为了建立起数据元素之间的关系,对于每个数据元素除了存放元素自身的信息外,还必须有包含指向该元素直接后继元素位置的信息,这两部分信息组成一个节点,即每个节点都有至少包含两个域,一个域存储数据元素信息,称为数据域,另一个域存储直接后继的地址,称为指针域
    typedef struct ListNode
    {
        int data;
        ListNode *next;
    }ListNode;
    当n 个元素的线性表通过每个节点的指针域连接像一条"链子",故形象称之为链表
     
    单链表的基本操作
    •  链表的初始化;
    •  链表的插入;
    •  链表的创建;
    •  链表节点的插入;
    •  链表节点的删除;
    •  链表的销毁;
    •  获取链表的长度;
    •  链表的倒置;
    •  链表的遍历;
     
    单链表的基本操作的完整代码实现
     
    注:下面代码实现的所有链表均是带头结点的链表,即头指针的data为空,初始化时使头指针->next = NULL,头指针->data不做处理。
    网上关于链表操作的博文带头结点和不带头结点的均有,没有一个统一的标准,其实原理是一样的,每个函数方法只要稍微修改就能实现响应的功能,看个人喜好,没有差别。以下代码带VS2012编译器中编译通过。
    #include <iostream>
    using namespace std;
    
    typedef struct ListNode
    {
        int data;
        ListNode *next;
    }ListNode;
    
    bool initList(ListNode **head);  //初始化链表
    void insertList(ListNode *head, int data); //尾插法插入函数
    ListNode *createList(int *arr, int len);  //创建链表
    bool destroyList(ListNode **head);        //摧毁链表
    bool ListInserLocateNum(ListNode * head, int i, int data);  //在带头结点的单链表的第i个位置之前插入元素
    bool ListDelete(ListNode *head, int i, int *data);   //删除第i个元素,并由data返回其值
    int getListLength(ListNode *head);   //获取链表的长度
    void reverseList(ListNode *head);  //链表倒置
    void ListTraverse(ListNode *head);   //遍历链表
    
    //初始化链表
    bool initList(ListNode **head)
    {
        *head = (ListNode *)malloc(sizeof(ListNode));
        if(*head == NULL)
        {
            return false;
        }
        (*head)->next = NULL;
        return true;
    }
    
    //创建链表
    ListNode *createList(int *arr, int len)
    {
        ListNode *p = NULL;
        bool flag = initList(&p);
        if(flag)
        {
            for(int i = 0; i < len; ++i)
            {
                insertList(p, arr[i]);
            }
            return p;
        }
        cout << "链表初始化失败" << endl;
        return NULL;
    }
    
    //尾插法
    void insertList(ListNode *head, int data)
    {
        ListNode *node = (ListNode *)malloc(sizeof(ListNode));
        node->data = data;
        node->next = NULL;
        ListNode *p = head;
        while(p->next != NULL)
        {
            p = p->next;
        }
        p->next = node;
    }
    
    //摧毁链表
    bool destroyList(ListNode **head)
    {
        ListNode *p;
        while(*head)
        {
            p = (*head)->next;
            free(*head);
            *head = p;
        }
        return 1;
    }
    
    //在带头结点的单链表的第i个位置之前插入元素
    bool ListInserLocateNum(ListNode * head, int i, int data)
    {
        ListNode *p = head;
        int j = 0;  //带头结点,故从0开始
        while(p != NULL && j < i-1)
        {
            j++;
            p = p->next;
        }
        if(p == NULL || j >= i)
            return false;
        ListNode *node = (ListNode *)malloc(sizeof(ListNode));
        node->data = data;
        node->next = p->next;
        p->next = node;
        return true;
    }
    
    //删除第i个元素,并由data返回其值
    bool ListDelete(ListNode *head, int i, int *data)
    {
        ListNode *p = head;
        int j = 0;
        while(p != NULL && j < i-1)
        {
            j++;
            p = p->next;
        } //该方法最多只能定位到最后一个节点
        if(p->next == NULL || j > i-1)
            return false;
        ListNode *pNext = p->next;
        *data = pNext->data;
        p->next = pNext->next;
        free(pNext);
        return true;
    }
    
    //获取链表的长度
    int getListLength(ListNode *head)
    {
        ListNode *p = head->next;
        int i = 0;
        while(p != NULL)
        {
            i++;
            p = p->next;
        }
        return i;
    }
    
    //链表倒置
    void reverseList(ListNode *head)
    {
        ListNode *p = head->next;
        ListNode *pReverse = NULL;
        while(p != NULL)
        {
            ListNode *pNext = p->next;
            p->next = pReverse;
            pReverse = p;
            p = pNext;
        }
        head->next = pReverse;
    }
    
    //遍历链表
    void ListTraverse(ListNode *head)
    {
        if(head == NULL)
            return;
        ListNode *p = head->next;
        while(p != NULL)
        {
            cout << p->data << ",";
            p = p->next;
        }
    }
    int main()
    {
        int arr[5] = {1, 2, 3, 4, 5};
        int len = sizeof(arr) / sizeof(arr[0]);
        ListNode *node = createList(arr, len);
        ListTraverse(node);
        cout << endl;
        reverseList(node);
        ListTraverse(node);
        cout << endl;
        cout << "length:" << getListLength(node) << endl;
        int flag = ListInserLocateNum(node, 3, 6);
        if(flag)
        {
            ListTraverse(node);
        }
        else
        {
            cout << "第i个位置超出链表的长度";
        }
        cout << endl;
        int deleteNum = 0;
        flag = ListDelete(node, 3, &deleteNum);
        if(flag)
        {
            ListTraverse(node);
        }
        else
        {
            cout << "你要删除的节点已超出链表的长度";
        }
        cout << endl;
        cout<< deleteNum << endl;
        flag = destroyList(&node);
        if(flag)
        {
            cout << "链表已销毁" << endl;
            ListTraverse(node);
        }
        system("pause");
        return 0;
    }
  • 相关阅读:
    iOS动画之模拟音量振动条
    LeetCode Reverse Linked List
    Android使用BroadCastRecevier广播实现接收短信,并利用Toast弹出显示内容
    Python+Django+SAE系列教程16-----cookie&amp;session
    初识MVC之建项
    【Android 系统开发】使用 Source InSight 阅读 Android 源代码
    ym—— Android网络框架Volley(终极篇)
    俯视数据库系统原理
    hdu 1269 迷宫城堡
    2014年湖北省TI杯大学生电子设计竞赛论文格式
  • 原文地址:https://www.cnblogs.com/evenleee/p/8474532.html
Copyright © 2011-2022 走看看