单链表的增删排序求长度的实现。

对于链表,我们可以知道他和算法会有相关。我们至少通过两组结构来存储:数组和链表。
接下来,我们来进行单链表的实现
在这里,我们可以进行增加,删除,求长度,排序。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
//定义了一个链表节点的数据类型
//在这里你要清楚什么事头结点,头指针,首节点,尾节点
//头节点的数据类型和首结点的是一模一样的。
//头节点是首节点前面的那个节点,头节点并不存放有效数据,
//头节点的就是为了方便链表的操作。
//确定一个链表只需 要知道头指针,
//链表最后的尾节点为空
//判断尾节点,只需要判断尾节点的指针域为空。
//
typedef struct Node
{
    int data;//数据域
    struct Node *pNext;
    //指针域,这个指针域指向下一个结点,类型必须和结构体类型一样,
    //所以才是struct Node类型
    //其实说白了就是递归,next存放的是地址,
}NODE, *PNODE;//要记住这里的的类型要加上struct Node 类型
//在这里NODE就是等价于struct Node ,PNODE等价于struct Node *

PNODE create_list()
{
    int len;//存放有效节点个数
    int i;
    int val;//存放用户输入节点的值
    //首先分配一个不存放有效数据的头结点

    PNODE pHead = (PNODE)malloc(sizeof(NODE));
    //
    //接下来判断malloc是否动态开辟成功
    if (NULL == pHead)
    {
        printf("动态开辟失败!\n");
        exit(1);//用来终止程序。
        //exit()函数一般是返回给操作系统的,
        //当函数里面的参数为非0时,程序终止,当参数为0时,函数继续。
    }

    PNODE pTail = pHead;//这里是对尾节点的创建;
    pTail->pNext = NULL;

    printf("输入你需要生成链表节点个数:");
    scanf("%d",&len);
    for (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放到尾节点的指针域里面去。
        pNew->pNext = NULL;//这里把新创建的节点变成尾节点。
        pTail = pNew;//把新创建的看作头指针。
    }

    return pHead;//返回头指针。方便后续操作
}

//遍历链表程序。
void traverse_list(PNODE pHead)
{
    //在这注意不能像数组一样对下标进行操作。因为链表是不连续的。
    //所以在这里进行指针操作。
    PNODE p=pHead->pNext;//首先的操作是将头指针域赋给一个指针变量
    while (NULL != p)//在这里如果p中不为空,则就向下一个进行移动
    {
        printf("%d  ", p->data);
        p = p->pNext;//当这里p为所指向的指针域为倒数第二个时,这时存放
        //的就是最后一个的地址,所以这是再进行一次循环,然后当p再移动的时候
        //这时p就为null了,退出循环。
    }
    printf("\n");
}
int is_empty(PNODE pHead)
{
    if (NULL == pHead->pNext)
    {
        return 1;
    }

        return 0;
}
int lenght_list(PNODE pHead)
{
    int len = 0;
    PNODE p = pHead->pNext;
    while (p)
    {
        len++;
        p = p->pNext;
    }
    return len;
}


void soert_list(PNODE pHead)
{
    int i = 0, j = 0, tmp = 0;
    int len = lenght_list(pHead);
    PNODE p,q;
    //在这我们应该知道,只要是线性结构的,排序方法都是一样的
    //所以在这你需要联想数组的排序方法。
    for (i = 0,p=pHead->pNext; i < len - 1; i++,p=p->pNext)//在这里给出一个结点的data
    {
        for (j = i+1,q=p->pNext; j < len; j++,q=q->pNext)//在这里与这个结点之后的结点进行对比,排序。
        {
            if ((p->data)>(q->data))
            {
                tmp = p->data;
                p->data = q->data;
                q->data = tmp;
            }
        }
    }
}

int insert_list(PNODE pHead, int n, int val)
{
    PNODE p = pHead;
    int i = 0;
    //在这里进行的是寻找咱们所需要插入的那个节点
    while (NULL != p&&i < n - 1)
    {
        p = p->pNext;
        i++;
    }

    if (i>n - 1 || NULL == p)
    {
        return 0;
    }
    //执行完全部上面的程序以后,这里就可以说明,用户所给的参数是有效的
    //接下来,我们就可以进行插入算法。
    PNODE pNew = (PNODE)malloc(sizeof(NODE));
    if (NULL == pNew)
    {
        printf("动态开辟失败!\n");
        exit(1);
    }
    pNew->data = val;
    PNODE q = p->pNext;
    p->pNext = pNew;
    pNew->pNext = q;
    return 1;
}


int delete_list(PNODE pHead, int n, int *pVal)
{
    PNODE p = pHead;
    int i = 0;
    while (NULL != p->pNext && i < n - 1)
    {
        p = p->pNext;
        i++;
    }
    if (i>n - 1 || NULL == p->pNext)
    {
        return 0;
    }
        PNODE q = p->pNext;
        *pVal = q->data;
        //输出p节点后的节点,这里要注意的是一定要记得free;
        p->pNext = p->pNext->pNext;
        free(q);
        q = NULL;
    return 1;
}
int main()
{
    int len=0;
    int n = 0;
    int val=0;
    int save = 0;
    PNODE pHead = NULL;//用来存放链表头结点的地址。
    pHead = create_list();
    //这个函数造一个链表出来,并且返回链表的头结点的地址赋给pHead
    //在这建立链表采用动态的建立链表。
    //透过pHead,就可以对链表每处进行访问。
    traverse_list(pHead);
    //输出链表,只需要传头指针即可。
    //接下来完成几个功能函数

    //判断链表是否为空
    if (is_empty(pHead))
    {
        printf("链表为空\n");

    }
    else
    {
        printf("链表不为空\n");
    }

    //接下来对链表求长度
    printf("输出链表长度:");
    len = lenght_list(pHead);
    printf("%d\n",len);

    //接下来完成链表的排序
    printf("输出链表排序后的结果:\n");
    soert_list(pHead);
    traverse_list(pHead);

    //接下来完成链表的插入
    //在这里你要给出所要在第n个节点的前面插入一个新的节点,这个节点的数值就是val。
    printf("请输入你所需要插入的节点所在的位置:");
    scanf("%d", &n);
    printf("请输入这个节点的值:");
    scanf("%d", &val);
    insert_list(pHead,n ,val);
    traverse_list(pHead);

    //接下来完成链表的删除
    printf("请输入你所需要删除的节点所在的位置:");
    scanf("%d", &n);
    if (delete_list(pHead, n, &save))
    {

        printf("删除元素%d成功\n",save);
    }
    else
    {
        printf("删除元素%d失败\n",save);
    }
    traverse_list(pHead);
    system("pause");
    return 0;
}

测试结果
这里写图片描述
希望如果有问题,大家多多提出!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值