线性表之链式表示

本文介绍了线性表的链式表示方法,强调了链式存储中数据元素在物理上非连续的特点,每个节点包含数据域和指针域,用于存储数据及其后继元素的地址。链式表示允许灵活的内存分配,并通过代码示例展示了其实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线性表链式表示方法

线性表的链式存储特点是用一组任意的存储单元存储线性表的数据元素(这组存取单元很可能在物理上不是连续的)。因此为了表示每个数据元素,出了存储其本身的信息之外,还的存储一个指示其后继的信息。这两部分信息组成数据元素的存储映像,称为结点。包括了一个数据域和一个指针域(为什么可以包括自己类型的指针呢?因为指针在32位CPU上表示4字节大小,大小固定)。


其原理及其实现都是比较简单的,代码如下所示:

#include <stdio.h>

#include <stdlib.h>

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


bool GetElem_L(LNode *pNode, int i, int *e)
{
    if (pNode == NULL || e == NULL)
    {
        return false;
    }

    LNode *p = pNode->next;
    int pos = 1;
    while (p && pos < i)
    {
        p = p->next;
        ++pos;
    }

    if (!p || pos > i)
    {
        return false;
    }

    *e = p->data;

    return true;
}

bool ListInsert_L(LNode *pNode, int i, int e)
{
    LNode *p = pNode;
    int pos = 0;
    while (p && pos < i - 1)
    {
        p = p->next;
        ++pos;
    }
    if (!p || pos > i - 1)
    {
        return false;
    }
    LNode *s = (LNode*)malloc(sizeof(LNode));
    s->data = e;
    s->next = p->next;
    p->next = s;

    return true;
}


bool ListDelete_L(LNode *pNode, int i, int *e)
{
    if (pNode == NULL || e == NULL)
    {
        return false;
    }

    LNode *p = pNode;
    int pos = 0;

    while (p->next && pos < i - 1)
    {
        p = p->next;
        ++pos;
    }
    if (!(p->next) || pos > i - 1)
    {
        return false;
    }
    LNode *q = p->next;
    p->next = q->next;
    *e = q->data;
    free(q);

    return true;
}


void CreateList_L(LNode **pNode, int n)
{
    if (pNode == NULL)
    {
        return;
    }

    *pNode = (LNode*)malloc(sizeof(LNode));
    (*pNode)->next = NULL;
    (*pNode)->data = 5;
    for (int i = 1; i <= n; i++)
    {
        LNode *p = (LNode*)malloc(sizeof(LNode));
        p->data =  i;
        p->next = (*pNode)->next;
        (*pNode)->next = p;

    }
}

void ListDestroy(LNode *pNode)
{
    while(pNode)
    {
        LNode *q = pNode;
        pNode = pNode->next;
        free(q);
    }
}

void tranverse(LNode *pNode)
{
    while(pNode)
    {
        printf("%d\n", pNode->data);
        pNode = pNode->next;
    }
}

int main()
{
    LNode *pList = NULL;
    CreateList_L(&pList, 4);
    ListInsert_L(pList, 1, 10);
    int e = 0;

    ListDelete_L(pList, 3, &e);
    printf("%d\n", e);

    tranverse(pList);


    ListDestroy(pList);
    return 0;
}

//=======================================================================================

#include <stdio.h>
#include <stdlib.h>

typedef struct tagLinkList
{
    int data;
    struct tagLinkList *pNext;
} LinkList;


LinkList *createList(unsigned int nodeNum)
{
    LinkList *pHeader = NULL;

    for(unsigned int i = 0; i < nodeNum; i++)
    {
        LinkList *pCur = (LinkList*)malloc(sizeof(LinkList));
        pCur->data = i;
        pCur->pNext = pHeader;
        pHeader = pCur;
    }
    return pHeader;
}

void tranverseList(LinkList *pList)
{
    while (pList != NULL)
    {
        printf("%d\n", pList->data);
        pList = pList->pNext;
    }
    printf("**********************\n");
}

LinkList *BubbleSortList(LinkList *pList) //单链表排序
{

    LinkList *q = NULL;
    LinkList *tail = NULL;
    LinkList *p=(LinkList*)malloc(sizeof(LinkList)); // 使指针p指向新开辟的结点
    p->pNext = pList; // 使新结点的next成员指向旧链表的头head
    pList = p; // 旧链表头head指向新结点
// 以上三条语句的作用是在旧链表head的前面增加一个结点

// 不严格来说,该语句等同于“head->pNext != tail”
//作用是,如果head所指结点的next成员为NULL,刚结束循环
    while (tail != pList->pNext)
    {
        p = pList;
        q = p->pNext;  // q总是指向"p所指结点"的下一结点
        while (q->pNext != tail)   // 当q->next的值为NULL是,表示已达链表结尾
        {
            if(p->pNext->data > q->pNext->data)  // 当前一结点的i值小于后一结点的i值执行下面的语句块
            {
                p->pNext = q->pNext;
                q->pNext = q->pNext->pNext;
                p->pNext->pNext = q;
            }  // 该语句块改变链表的连接顺序,参见下图
            p = p->pNext;
            q = p->pNext; // 以上两条语句使p、q分别指向各自的下一结点,过程可以参考对数组的冒泡算法
        }
        tail = q; // 使tail指向"每次排序后的q所指的结点",作用是为下一循环设置条件表示式,从而使每次内循环的次数减少
    }
    p = pList->pNext;  // p指向head->next,也就是p指向旧链表的表头
    free(pList);  // 释放在函数内新开辟的结点
    return(p);
}


int main(void)
{
    LinkList *pList = createList(0);
    tranverseList(pList);

    pList = BubbleSortList(pList);
    tranverseList(pList);

}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值