线性表的链式存储结构---单链表

来源:互联网 发布:淘宝公众号 编辑:程序博客网 时间:2024/05/16 00:59

线性表的链式存储结构是指可以使用任意一组内存单元来存储线性表的数据元素,这些内存单元可以连续,也可以不连续;这就意味着数据元素可以存储在内存没有被占用的任意位置。
单链表是线性表的链式存储结构的一种,为什么称之为单链表,是因为结点中只含有一个指针域存储下一个元素的地址;结点又是什么?
在链式存储结构中,一个数据元素除了存储自身数据元素信息,还要存储它的后继元素的存储地址,把存储数据元素的域称为数据域,把存储后继元素位置的域称为指针域;这两部分信息的组成这个数据元素的存储形式,称之为结点;存一个数据元素既要存储这个元素本身信息,也要存储它下一个元素的地址;比如:

/*结点*/struct Node{    int data;//数据域--存储结点本身信息    struct Node *pNext;//指针域--存储下一个节点的地址};

链表中的专业术语:
首节点:
第一个有效节点
尾节点:
最后一个有效节点
头结点:
第一个有效节点之前的那个节点
头结点并不存放有效数据
加头结点的目的主要是为了方便对链表的操作
头指针:
指向头结点的指针变量(存放头结点的地址)
尾指针:
指向尾节点的指针变量
如果希望通过一个函数来对链表进行处理,我们至少需要接受链表的那些信息:
确定一个链表只需要一个参数 :头指针
因为我们通过头指针可以推算出链表的其他所有信息
单链表示意图:
这里写图片描述

下面使用c语言代码演示一下 单链表的创建,插入,删除以及整表删除
先声明一个结点结构体:

#include <stdio.h>#include <malloc.h>#include <stdlib.h>#include <time.h>/*链表的结点*/typedef struct Node{    int data;//数据域--存储结点本身信息    struct Node *pNext;//指针域--存储下一个节点的地址}NODE,*PNODE;

链表的创建,分为两种方式一种是头插法,另一种是尾插法;
头插法:让新插入的结点始终在首结点的位置;
尾差法:让新插入的结点始终在尾结点的位置;

/*创建一个单链表有两种方式,一种是头插法,一种是尾差法*/PNODE createLinked(int n){    PNODE pHead = (PNODE)malloc(sizeof(NODE));//分配NODE类型的字节大小    if(pHead == NULL)    {        printf("动态内存分配失败!\n");        exit(-1);//结束程序    }    pHead->pNext = NULL;    pHead->data  = n;//头结点的数据域可以用来存储线性表的长度等附加信息    srand(time(0));//srand()函数可以设置一个随机数种子生成器 time(0)表示生成当前的时间    //1.头插法     /*    int i;    for(i=0;i<n;i++)    {    PNODE p = (PNODE)malloc(sizeof(NODE));    if(p == NULL)    {    printf("动态内存分配失败!\n");    exit(-1);//结束程序    }    p->data  = rand()%100+1;//这里要产生100以内的数字    p->pNext = pHead->pNext;//让新结点指向原来头结点的位置    pHead->pNext = p;//插入到表头,这样新插入的节点就会变成头结点    }    */    //2.尾插法    PNODE pTail = pHead;//定义一个尾指针    int j;    for(j=0;j<n;j++)    {        PNODE p = (PNODE)malloc(sizeof(NODE));//生成一个新结点        if(p == NULL)        {            printf("动态内存分配失败!\n");            exit(-1);        }        p->data = rand()%100+1;//新结点的数据域赋值        p->pNext = NULL;//新结点的数据域先暂时置空        pTail->pNext = p;//让原先链表的尾结点的指针域指向这个新结点地址        pTail = p;//把新结点的地址赋给尾结点    }    return pHead;}

单链表的插入

/*单链表的插入 pos:链表第几个位置 val:插入的数值*/bool insertLinked(PNODE pHead,int pos,int val){    int i = 0;    PNODE p = pHead;    while(p&&i<pos-1)//寻找第pos-1个结点    {        p = p->pNext;        ++i;    }    if(i>pos-1||!p)    {        return false;//第pos个结点不存在    }    PNODE pNew = (PNODE)malloc(sizeof(NODE));//生成一个新的结点    if(!pNew)    {        printf("动态内存分配失败!\n");        exit(-1);    }    pNew->data = val;    pNew->pNext = p->pNext;//将结点p的后继结点赋值给pNew的后继结点    p->pNext = pNew;//将新结点pNew赋值给p的后继    return true;}

单链表的删除

/*单链表结点的删除*/bool deleteLinked(PNODE pHead,int pos,int *pVal){    int i = 0;    PNODE p = pHead;    while(p->pNext&&i<pos-1)//寻找第pos-1个结点    {        p = p->pNext;        ++i;    }    if(i>pos-1||!p->pNext)    {        return false;//第pos个结点不存在    }    PNODE q = p->pNext;//要删除的结点    *pVal = q->data;    //删除p结点后面的结点    p->pNext = p->pNext->pNext;    free(q);//让系统回收此节点,释放内存    q = NULL;    return true;}

整表的删除

/*将单链表置空表*/bool clearLinked(PNODE pHead){    PNODE p = pHead->pNext;//指向首结点    PNODE q;    while(p)//判断是否到了表尾    {        q = p->pNext;//当前结点的下一个结点        free(p);//释放当前结点        p = q;//将下一个结点赋给p    }    pHead->pNext = NULL;//将头结点指针域置为空    return true;}
0 0
原创粉丝点击