单链表的基本操作实现

1、写这篇博文的原因

C语言有三个重要部分:流程控制、函数、指针。

对于指针,单单了解它的简单运用是远远不够的,最重要的是学习链表。所以这篇文章通过用C语言实现链表的一些基本操作和总结,希望对C语言的指针有更新的理解和认识。

2、单链表的定义

单链表是通过一组任意的存储单元来存储线性表中的数据元素,这些存储单元可以是连续的也可以是不连续的。为了建立起数据元素之间的关系,对于每个数据元素除了存放元素自身的信息外,还必须有包含指向该元素直接后继元素位置的信息,这两部分信息组成一个节点,即每个节点都有至少包含两个域,一个域存储数据元素信息,称为数据域,另一个域存储直接后继的地址,称为指针域

typedef struct ListNode
{
    int data;
    ListNode *next;
}ListNode;

当n 个元素的线性表通过每个节点的指针域连接像一条"链子",故形象称之为链表

3、单链表的基本操作

  • 链表的初始化;
  • 链表的插入;
  • 链表的创建;
  • 链表节点的插入;
  • 链表节点的删除;
  • 链表的销毁;
  • 获取链表的长度;
  • 链表的倒置;
  • 链表的遍历;

4、单链表的基本操作的完整代码实现

注:下面代码实现的所有链表均是带头结点的链表,即头指针的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;
}

原文地址:https://www.cnblogs.com/evenleee/p/8474532.html

时间: 2024-10-06 05:15:10

单链表的基本操作实现的相关文章

《实验课---单链表的基本操作》

//线性表---链表的基本操作#include<stdio.h>#include<stdlib.h>#include<conio.h>#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1#define NULL 0typedef int Status; //函数结果状态代码typedef int ElemType; //数据元素类型//------线性表的单链表存储结构

用Java实现单链表的基本操作

笔试题中经常遇到单链表的考题,下面用java总结一下单链表的基本操作,包括添加删除节点,以及链表转置. package mars; //单链表添加,删除节点 public class ListNode { private Node head; public ListNode(){ head=null; } //在链表前添加节点 public void addpre(int dvalue){ Node n=new Node(dvalue); if(head==null){ head=n; }els

单链表的基本操作(第一篇)

  学习数据结构的笔记 1.在线性表的链式存储中,头指针与头结点之间的根本区别以及头结点与开始结点的关系: 链表的头指针一般指向其第一个结点,他有标识链表的作用.头结点的作用在于统一相关操作,头结点的数据域一般没有意义,在某些情况下可以存放链表长   度.如果链表含有头结点,无论链表是   否为空,头指针均不为空.开始结点也就是链表中存储数据的第一个结点,它是头结点后边的第一个结点. 2.比较顺序表和链表各自的特点: (1)存储分配的方式:顺序表的存储空间是静态分配的.链表的存储空间是动态分配的

单链表的基本操作

直接上代码 #include<stdio.h> #include<stdlib.h> //结构定义 typedef struct node{ int data; //数据域 struct node *next; //指针域 }LinkList; //创建单链表 void CreateLinkList(LinkList *L){ L->next = NULL; } //尾插法 void Insert_Tail(LinkList *L,int x){ LinkList *p; p

D_S 单链表的基本操作

//  main.cpp #include <iostream> using namespace std; #include "Status.h" #include "LinkList.h" int main() { LinkList L; int n,i; ElemType e; InitList(L); cout<<"\nL="; ListTraverse(L); cout<<"\n请设置将向线性

C语言实现单链表的基本操作及其部分面试题

//单链表的基本数据类型及其结构 typedef int DataType; typedef struct LinkNode { DataType data; struct LinkNode *next; }LinkNode,*pLinkNode,*pLinkList; //单链表的初始化 void InitLinkList(pLinkList* pHead)//初始化 { assert(pHead); *pHead = NULL; } //当尾插,头插,插入时都需要建立一个新的结点,为方便建立

单链表的基本操作(建立.遍历.添加.删除)

有n个元素,我们把他们用链表表示,执行一些操作在某个位置添加一个数,或者删除某个位置的数: 输入合法的代码: #include<iostream> #include<stdio.h> #include<stdlib.h> using namespace std; struct node { int date; struct node *next; }; node *CreatList(node *head, int n); void TravList(node *hea

单链表及基本操作。(含练习)

1 ////////////////////////////////////////////// 2 //单链表的初始化,建立,插入,查找,删除. // 3 //(以及部分练习) // 4 //Author:Bread // 5 //Date: 2014.12.28 // 6 //Update 1th:2014.12.31 // 7 ////////////////////////////////////////////// 8 #include <stdio.h> 9 #include &l

单链表的基本操作(一)

一.单链表的初始化: 1.生成新结点作为头结点,用头指针L指向头结点 2.头结点的指针域置空 Status InitList(LinkList &L) { //构造一个空的单链表L L=new LNode ;//生成新结点作为头结点,用头指针L指向头结点 L-next=NuLL;//头结点的指针域置空 return ok; } 二.取值: 1.用指针p指向首元结点,用j做计数器初值赋为1 2.从首元结点开始依次顺着链域next向下访问,只要指向当前结点的指针p不为空(NULL),并且没有到达序号