数据结构学习--对链表(单链表)的一些操作

本篇博客主要介绍了对于单链表的一些基本的操作,包括:判断链表是否为空、计算链表的长度、链表中插入值、链表中删除值、链表元素排序。

其中,插入、删除难度最大,需要对于链表的创建有一定的理解。元素的排序其次,其算法可参照数组的排序。判断是否为空和计算链表的长度则比较简单。

插入操作的理解帮助:插入操作与链表的创建操作有几分相似之处,两者均生成新的节点。链表中对于生成新的节点的操作需要通过中介pTail节点来进行,例如,在创建链表的时候通过中介pTail节点间接地把新生成的节点与前一节点连接,而不是直接对前后两个节点进行操作。对于插入,即把新生成的节点的地址给到前一节点的地址域,新节点的地址域存放后一节点的地址。

下面是链表的相关操作的函数,包含了链表的创建和遍历函数

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

typedef struct node
{
    int data;
    struct node * pNext;
}NODE, *PNODE;

PNODE create_list(void); //创建链表
void traverse_list(PNODE pHead); //遍历链表内的元素并输出
bool is_empty(PNODE pHead); //判断链表是否为空
int length_list(PNODE pHead); //计算链表的长度
bool insert_list(PNODE pHead, int pos, int val); //在链表的第pos位插入val
bool delete_list(PNODE pHead, int pos, int * pVal); //删除链表的第pos位,删除的值的地址保存在pVal上
void sort_list(PNODE pHead); //对链表内的数据进行排序,链表的排序方法可以参考数组的排序方法,唯一的不同点是:数组是连续的,链表不是连续的。但两者都是线性的结构。

int main(void)
{
    int i = 0;
    int val = 0;
    PNODE pHead = NULL;
    pHead = create_list();
    traverse_list(pHead);

    if ( is_empty(pHead) )
    {
        printf("链表为空,程序终止!");
        exit(-1);
    }
    else
    {
        printf("链表不为空!\n");
    }

    i = length_list(pHead);
    printf("%d\n", i);

    insert_list(pHead, 3, 99);
    traverse_list(pHead);

    sort_list(pHead);
    traverse_list(pHead);

    delete_list(pHead, 4, &val);
    printf("删除元素是%d\n", val); //这句话可以直接写在delete_list()函数里,由delete_list()进行输出,同时delete_list()函数保留了删除的值,其地址存放在&val里
    traverse_list(pHead);

    return 0;
}

PNODE create_list(void)
{
    int val, len;
    printf("请输入链表的长度:len = ");
    scanf("%d", &len);

    PNODE pHead = (PNODE)malloc(sizeof(NODE));
    pHead->pNext = NULL;
    if (NULL == pHead)
    {
        printf("头结点生成失败!程序终止!\n");
        exit(-1);
    }
    PNODE pTail;
    pTail = pHead;

    for (int i=0; i<len; i++)
    {
        printf("请输入链表第%d个元素的值:", i+1);
        scanf("%d", &val);

        PNODE pNew = (PNODE)malloc(sizeof(NODE));
        if (NULL == pNew)
        {
            printf("新节点生成失败,程序终止!\n");
            exit(-1);
        }
        pNew->data = val;
        pTail->pNext = pNew;
        pNew->pNext = NULL;
        pTail = pNew;
    }
    return pHead;
}

void traverse_list(PNODE pHead)
{
    PNODE p = pHead->pNext;
    while (NULL != p)
    {
        printf("%d ", p->data);
        p = p->pNext;
    }
    printf("\n");
    return;
}

bool is_empty(PNODE pHead)
{
    if (NULL == pHead->pNext)
    {
        printf("链表为空!");
        return true;
    }
    else
        return false;
}

int length_list(PNODE pHead)
{
    PNODE p = pHead->pNext;
    int i = 0;
    while(NULL != p)
    {
        i++;
        p = p->pNext;
    }
    return i;
}

bool insert_list(PNODE pHead, int pos, int val)
{
    PNODE pNew = (PNODE)malloc(sizeof(NODE));
    pNew->data = val;
    pNew->pNext = NULL;

    PNODE p1 = pHead->pNext;
    for (int i=0; i<pos-2; i++)
    {
        p1 = p1->pNext;
    } //循环结束后,p1存放的是原链表第pos-1个节点的地址域
    PNODE p;
    p = p1->pNext;
    p1->pNext = pNew;
    pNew->pNext = p;
    printf("第%d个元素插入%d插入成功!\n", pos, val);

    return true;
}

void sort_list(PNODE pHead)
{
    PNODE p, q;;
    int i, j, t;
    int len = length_list(pHead);

    for (i=0, p=pHead->pNext; i<len-1; i++, p=p->pNext)
    {
        for (j=0, q=pHead->pNext; j<len-1-i; j++, q=q->pNext)
        {
            if (q->data < q->pNext->data)
            {
                t = q->data;
                q->data = q->pNext->data;
                q->pNext->data = t;
            }
        }
    }
    //此种链表排序方法对应于以下数组排序方法
    /*
    for (i=0; i<len-1; i++)
    {
        for (j=0; j<len-1-i; j++)
        {
            if (a[j] < a[j+1])
            {
                t = a[j];
                a[j] = a[j+1];
                a[j+1] = t;
            }
        }
    }

    /*
    for (i=0, p=pHead->pNext; i<len-1; i++, p=p->pNext)
    {
        for (j=i+1, q=p->pNext; j<len; j++, q=q->pNext)
        {
            if (p->data < q->data)
            {
                t = p->data;
                p->data = q->data;
                q->data = t;
            }
        }
    }
    */
    //此种链表排序方法对应于如下数组排序方法
    /*
    for (i=0; i<len-1; i++)
    {
        for (j=i+1; j<len; j++)
        {
            if (a[i] < a[j])
            {
                t = a[i];
                a[i] = a[j];
                a[j] = t;
            }
        }
    }
    */
}

bool delete_list(PNODE pHead, int pos, int * pVal)
{
    PNODE p = pHead;
    int len = length_list(pHead);
    if (NULL==pHead->pNext || pos>len || pos<0)
    {
        printf("链表为空 or 要删除的链表的元素位置大于链表的长度 or pos数据出错,无法进行删除元素操作,程序终止!\n");
        exit(-1);
    }
    for (int i=0; i<pos-1; i++)
    {
        p = p->pNext;
    } //循环结束,找到第pos-1个节点,p为第pos-1个节点的地址域存储的地址
    * pVal = p->pNext->data;
    p->pNext = p->pNext->pNext;

    return true;
}

/*
//进行链表元素删除的另一种函数写法
bool delete_list(PNODE pHead, int pos, int * pVal)
{
    int i = 0;
    PNODE p = pHead;

    while (NULL!=p->pNext && i<pos-1)
    {
        p = p->pNext;
        i++;
    }

    if (i>pos-1 || NULL==p->pNext)
        return false;

    PNODE q = p->pNext;
    * pVal = q->data;

    p->pNext = p->pNext->pNext;
    free(q);
    q = NULL;

    return true;
}
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值