数据结构之单链表(C实现)

list.h

#ifndef LIST_H
#define LIST_H

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

//定义单链表结点
typedef struct _node
{
    int data;   //数据
    struct _node *next; //指向下一结点
}node,*pNode;

//创建链表
node *create_list();

//从链表头后插入数据
int insert_listHead(pNode head,int data);

//从链表尾后插入数据
int insert_listTail(pNode head, int data);

//遍历链表,并显示每个结点的数据
int show_listData(pNode head);

//求链表中的结点个数 (不包括链表头,指真正存放数据的结点数目)
int getNodeNum(pNode head);

//根据索引查找结点,找到返回所找结点 index=0,对应头结点(不存放数据) index=1,对应第一个数据结点
pNode find_nodeByIndex(pNode head,int index);

//根据数据查找第一个符合结点(后面也可能有结点的数据为所找数据),找到返回所找结点
pNode find_nodeByData(pNode head,int data);

//指定位置插入结点数据
int insert_dataInPos(pNode head,int data,int index);

//从链表中删除第index个结点  index范围为1-nodeNum
int delete_listIndex(pNode head,int index);

//删除整个链表
int delete_listAll(node **head);

//根据索引查找结点,找到修改其值
int modify_nodeByIndex(pNode head,int index,int data);

//将链表排序 ==0,升序  ==1,降序
int sort_list(pNode head,int sortType);

#endif // LIST_H

 

list.c

#include "list.h"

/*************单链表测试程序************/

//创建链表
node *create_list()
{
    pNode head = (pNode)malloc(sizeof(node));
    if(!head)
    {
        printf("malloc error!\n");
//        exit(-1);   //在iostream中定义
        return NULL;
    }

    head->data = 0;
    head->next = NULL;  //不用指向head,由于不是循环链表且是单链表的尾结点的next腰指向NULL

    return head;
}

//从链表头后插入结点数据
int insert_listHead(pNode head,int data)
{
    //检测链表是否存在
    if(!head)
    {
        printf("list isnot exist!\n");
        return -1;
    }

    pNode tmpNode = (pNode)malloc(sizeof(node));    //存放插入数据的结点
    if(!tmpNode)
    {
        printf("malloc error!\n");
        return -1;
    }

    //将插入数据存入要插入链表的结点
    tmpNode->data = data;
    //将tmpNode插入链表头后
    tmpNode->next = head->next;
    head->next = tmpNode;

    return 0;
}

//从链表尾后插入结点数据
int insert_listTail(pNode head, int data)
{
    //检测链表是否存在
    if(!head)
    {
        printf("list isnot exist!\n");
        return -1;
    }

    pNode tmpNode = (pNode)malloc(sizeof(node));    //存放插入数据的结点
    if(!tmpNode)
    {
        printf("malloc error!\n");
        return -1;
    }

    //将插入数据存入要插入链表的结点
    tmpNode->data = data;
    //将tmpNode插入链表尾后
    tmpNode->next = NULL;   //插入链表插入链表尾后,成为新的尾结点,next要指向NULL

    pNode cur = head;
    //找到链表尾结点
    while(cur->next)    //尾结点的next指向NULL,跳出时的cur即为尾结点
    {
        cur = cur->next;
    }

    cur->next = tmpNode;    //原先尾结点的next指向插入结点

    return 0;
}

//遍历链表,并显示每个结点的数据
int show_listData(pNode head)
{
    //检测链表是否存在
    if(!head)
    {
        printf("list isnot exist!\n");
        return -1;
    }

    //检测链表是否为空  (“为空”与“不存在”不同,为空说明只有一个结点,刚创建还未插入任何结点)
    if(!head->next)
    {
        printf("list isnot exist!\n");
        return -1;
    }

    pNode cur = head->next; //头结点数据域不保存插入数据,第二个结点才是第一个插入结点
    while(cur)
    {
        printf("%d ",cur->data);
        cur = cur->next;
    }
    printf("\n");

    return 0;
}

//求链表中的结点个数 (不包括链表头,指真正存放数据的结点数目)
int getNodeNum(pNode head)
{
    int nodeNum = 0;    //结点数目

    //判断链表是否存在
    if(!head)
    {
        printf("list isnot exist!\n");
        return -1;
    }
    //------
    //判断链表是否为空
    if(!head->next)
    {
        printf("list is NULL!\n");
        return -1;
    }

    pNode cur = head->next;
    while(cur)
    {
        nodeNum++;
        cur = cur->next;
    }

    return nodeNum;
}

//根据索引查找结点,找到返回所找结点 index=0,对应头结点(不存放数据) index=1,对应第一个数据结点
pNode find_nodeByIndex(pNode head,int index)
{
    //判断链表是否存在
    if(!head)
    {
        printf("list isnot exist!\n");
        return NULL;
    }
    //------
    //判断链表是否为空
    if(!head->next)
    {
        printf("list is NULL!\n");
        return NULL;
    }
    //------
    int nodeNum = getNodeNum(head);
    if(index<=0 || index > nodeNum)   //索引必须在允许范围 (1-nodeNum)
    {
        printf("pos out of range!\n");
        return NULL;
    }

    int i = 0;
    pNode cur =  head;
    while(cur)
    {
        i++;
        cur = cur->next;
        if(i==index)
            return cur;
    }

    return NULL;    //不返回,有警告
}

//根据数据查找第一个符合结点(后面也可能有结点的数据为所找数据),找到返回所找结点
pNode find_nodeByData(pNode head,int data)
{
    //判断链表是否存在
    if(!head)
    {
        printf("list isnot exist!\n");
        return NULL;
    }
    //------
    //判断链表是否为空
    if(!head->next)
    {
        printf("list is NULL!\n");
        return NULL;
    }

    pNode cur =  head->next;
    while(cur)
    {
        if(cur->data == data)
            return cur;
        cur = cur->next;
    }

    return NULL;
}

//指定位置插入结点数据
int insert_dataInPos(pNode head,int data,int index)
{
    //判断链表是否存在
    if(!head)
    {
        printf("list isnot exist!\n");
        return -1;
    }
    //------
    //判断链表是否为空
    if(!head->next)
    {
        printf("list is NULL!\n");
        return -1;
    }
    //------
    int nodeNum = getNodeNum(head);
    if(index<=0 || index > nodeNum)   //指定插入位置必须在允许范围
    {
        printf("pos out of range!\n");
        return -1;
    }

    //由于find_nodeByIndex的参数2范围限制为1-nodeNum,所以index在那里不能为1,要>=2
    if(index==1)    //插入到位置1,相当于插入头结点后面
    {
        insert_listHead(head,data);
    }
    else    //index范围为2-nodeNum
    {
        pNode tmpNode = (pNode)malloc(sizeof(node));
        if(!tmpNode)
        {
            printf("malloc error!\n");
            return -1;
        }
        tmpNode->data = data;

        //获得插入位置的前一个结点-insertFrontNode(新数据结点插入到该结点后面)
        pNode insertFrontNode = find_nodeByIndex(head,index-1);
        if(!insertFrontNode)   //未找到要被插入的结点
        {
            printf("no find insertFrontNode!\n");
            return -1;
        }

        //若index=2,相当于新数据结点插入到原数据结点1后面,所以需要找到原数据结点1
        tmpNode->next = insertFrontNode->next;
        insertFrontNode->next = tmpNode;
    }

    return 0;
}

//从链表中删除第index个结点  index范围为2-nodeNum
int delete_listIndex(pNode head,int index)
{
    //判断链表是否存在
    if(!head)
    {
        printf("list isnot exist!\n");
        return -1;
    }
    //------
    //判断链表是否为空
    if(!head->next)
    {
        printf("list is NULL!\n");
        return -1;
    }
    //------
    int nodeNum = getNodeNum(head);
    if(index<=1 || index > nodeNum)   //index必须在允许范围
    {
        printf("pos out of range!\n");
        return -1;
    }

    pNode front =  find_nodeByIndex(head,index-1);    //找到要删除结点的前一个结点
    if(!front)
    {
        printf("no find!\n");
        return -1;
    }
    //---------
    pNode cur =  find_nodeByIndex(head,index);    //找到要删除结点
    if(!cur)
    {
        printf("no find!\n");
        return -1;
    }

    //删除该结点
    front->next = cur->next;
    free(cur);
    cur = NULL;

    return 0;
}

//删除整个链表
int delete_listAll(node **head)
{
    if(*head == NULL)
    {
        printf("list isnot exist!\n");
        return -1;
    }

    node *cur = (*head)->next;

    while(cur)
    {
        node *tmp = cur;

        //在free(tmp);后面,那时cur==tmp已经被释放,cur = cur->next不能正常执行了
        cur = cur->next;

        free(tmp);
        tmp = NULL;
    }

    free(*head);
    (*head) = NULL;

    return 0;
}

//根据索引查找结点,找到修改其值
int modify_nodeByIndex(pNode head,int index,int data)
{
    pNode modifyNode =  find_nodeByIndex(head,index); //找到要修改的结点
    modifyNode->data = data;

    return 0;    //不返回,有警告
}

//将链表排序 ==0,升序  ==1,降序
int sort_list(pNode head,int sortType)
{
    //判断链表是否存在
    if(!head)
    {
        printf("list isnot exist!\n");
        return -1;
    }
    //------
    //判断链表是否为空
    if(!head->next)
    {
        printf("list is NULL!\n");
        return -1;
    }

    int nodeNum = getNodeNum(head);

    int i,j;
    for(i = 0; i < nodeNum - 1; i++) //冒泡排序法
    {
        for(j = 0; j < nodeNum - 1 - i; j++)
        {
            //第一次获取0,1结点 第二次获取1,0结点
            node *t_first = find_nodeByIndex(head,j+1);
            node *t_second = find_nodeByIndex(head,j+2);

            if(sortType == 0)   //升序
            {
                if(t_first->data > t_second->data)
                {
                    //交换2个结点的值
                    int tmp = t_first->data;
                    t_first->data = t_second->data;
                    t_second->data = tmp;
                }
            }
            else if(sortType == 1)  //降序
            {
                if(t_first->data < t_second->data)
                {
                    int tmp = t_first->data;
                    t_first->data = t_second->data;
                    t_second->data = tmp;
                }
            }
            else
            {
                printf("parame error!\n");
                return -1;
            }

        }
    }

    return 0;
}

main.c

#include <iostream>
#include <stdio.h>
#include <malloc.h>
#include "list.h"

using namespace std;

pNode tmpNode;
int main(void)
{
    //创建链表
    tmpNode = create_list();
    if(!tmpNode)
    {
        printf("malloc error!\n");
        return -1;
    }

    //插入1,3,5,7,9到链表中
    for(int i=0;i<10;i++)
    {
        insert_listHead(tmpNode,++i);
    }

    //插入结点数据
    insert_dataInPos(tmpNode,12,2);

    //获取结点数目
    printf("nodeNum=%d\n",getNodeNum(tmpNode));

    //遍历显示结点数据
    printf("showList: ");
    show_listData(tmpNode);

    //根据索引,返回第3个数据结点 index范围为1-nodeNum
    pNode t_node = find_nodeByIndex(tmpNode,3);
    if(!t_node)    //有可能未找到,则返回NULL,那执行t_node->data会造成程序崩溃
        printf("no find!\n");
    else
        printf("t_data:data=%d\n",t_node->data);
    //返回数据为1的结点
    pNode t_node1 = find_nodeByData(tmpNode,1);
    if(!t_node1)
        printf("no find!\n");
    else
        printf("t_data:data=%d\n",t_node1->data);

    //从链表中删除第1个结点  index范围为2-nodeNum
    delete_listIndex(tmpNode,2);
    printf("showList: ");
    show_listData(tmpNode);

    //升序后显示结点数据
    sort_list(tmpNode,0);
    printf("sortUp showList: ");
    show_listData(tmpNode);

    //降序后显示结点数据
    sort_list(tmpNode,1);
    printf("sortUp showList: ");
    show_listData(tmpNode);

    //删除所有结点
    delete_listAll(&tmpNode);
    printf("showList: ");
    show_listData(tmpNode);


}

 

结果运行图:

 

转载于:https://www.cnblogs.com/linuxAndMcu/p/7535675.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值