单向链表操作(C语言)

该代码包含单向链表的建立,追加,遍历,删查改,判空,返回尾结点和中间节点,额外包含了单向链表的合并,排序,和将单向链表转换成循环链表.

注意:
该链表为带头节点的单向链表,头节点的数据域为-1.
将链表改为循环链表后,遍历操作不再适用于循环链表

代码如下.

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

typedef struct node
{
    int data;                //链表的数据域
    struct node * next;     //链表的指针域
}node;

//节点初始化
node * create_node()
{
    node *p = (node*)malloc(sizeof(node));
    p->data = -1;
    p->next = NULL;
}

//建立链表,尾部增加
node *link_list(int d[], int size)
{
	int i;
    node *head = create_node();
    node *tail = head;          //尾节点,此时尾结点就是头结点
    for(i = 0;i < size;i++)
    {
        node *p = (node *)malloc(sizeof(node));
        p->data = d[i];
        p->next = NULL;
        tail->next = p;
        tail = p;               //p变为尾节点
    }
    return head;
}

//追加一个节点(尾部追加)
void append(node *head,int elem)
{
    node *p = create_node();
    p->data = elem;
    node *s = head;
    while(s->next != NULL)
    {
        s = s->next;
    }
    s->next = p;
}

//返回链表长度
int len(node *head)
{
    node *s = head;
    int count = 0;
    for(;s != NULL;count++)
    {
        s = s->next;
    }
    return count;
}

//插入元素到链表之中
void insert(node *head,int i,int elem)
{
    //如果插入元素的位置非法,则退出程序
    if(i < 1)
    {
        printf("插入错误,程序终止!");
        exit(0);
    }

    //如果插入元素的位置大于链表的长度,则追加一个节点
    else if(i >= len(head)+1)
    {
        append(head,elem);
    }

    //正常插入元素
    else if(i < len(head) && i > 1)
    {
        node *p = head;
        node *s = create_node();
        int n;
        for(n = 1;n < i;n++)
        {
            p = p->next;
        }
        s->next = p->next;
        p->next = s;
        s->data = elem;
    }
}

//删除某个位置上的元素
void deleteelem(node *head,int i)
{
    //判断位置是否合法
    if(i < 1 || i > len(head))
    {
        printf("删除非法,程序终止!");
        exit(0);
    }

    node *p = head;
    node *q;
    int n;
    for(n = 1;n < i;n++)
    {
        p = p->next;
        q = (p->next)->next;
    }
    node *s = p->next;
    free(s);
    p->next = q;
}

//查找某个位置上的元素
int findelem_address(node *head,int i)
{
    //判断位置是否合法
    if(i < 1 || i > len(head))
    {
        printf("查找非法,程序终止!");
        exit(0);
    }

    node *p = head;
    int n;
    for(n = 0;n < i;n++)
    {
        p = p->next;
    }
    return p->data;
}

//修改某个位置上的元素
void change(node *head,int i,int elem)
{
    //判断位置是否合法
    if(i < 1 || i > len(head))
    {
        printf("修改非法,程序终止!");
        exit(0);
    }

    node *p = head;
    int n;
    for(n = 0;n < i;n++)
    {
        p = p->next;
    }
    p->data = elem;
}

//判断链表是否为空
int isempty(node *head)
{
    return (head == NULL);
    //  返回1代表链表为空
    //  返回0代表链表不为空
}

//遍历链表
void display(node *head)
{
    //判断链表是否为空
    if(isempty(head))
    {
        printf("链表为空,程序终止!");
        exit(0);
    }
    else
    {
        printf("此时有%d个节点\n",len(head));
        node *p = head;
        for(;p != NULL;p=p->next)
        {
            printf("The data is %d\n",p->data);
        }
    }
}

//销毁链表
void distory(node *head)
{
    node *p = head;
    for(;head != NULL;)
    {
        head = head->next;
        free(p);
        p = head;
    }
    printf("链表已销毁\n");
}

//链表元素的排序
void sortlist(node *head)
{
    node *p = head->next;
    node *s = p;
    int temp;
    while(p->next != NULL)
    {
        s = p->next;
        while(s != NULL)
        {
            if(p->data > s->data)
            {
                temp = p->data;
                p->data = s->data;
                s->data = temp;
            }
            s = s->next;
        }
        p = p->next;
    }
    
}

//将链表合并
void mergelist(node *p1,node *p2)
{
    node *p = p2->next;
    for(;p != NULL;p = p->next)
    {
        append(p1,p->data);
    }
}

//得到指向尾结点的指针
node * gettail(node *head)
{
    node *p = head->next;
    while(p->next != NULL)
    {
        p = p->next;
    }
     return p;
}

//将一个链表变成循环链表
void circulationlist(node *head)
{
    node *p = gettail(head);
    p->next = head->next;
}

//找到链表中点
node *findmiddle(node *head)
{
    node* slow=head;
    node* fast=head;
    if(head==NULL)
        return NULL;
    if(head->next==NULL)
        return head;
    while(fast->next!=NULL && fast->next->next!=NULL)
    {
        fast=fast->next->next;
        slow=slow->next;
    }
    return slow;
}

int main()
{
    int a[5] = {1,2,3,4,5};
    int size_ = sizeof(a)/sizeof(int);
    printf("创建链表\n");

    node *p = link_list(a,size_);       //创建链表1
    node *s = link_list(a,size_);       //创建链表2
    display(p);

    append(p,6);                        //追加一个元素
    display(p);

    insert(p,2,3);                      //插入一个元素
    display(p);

    deleteelem(p,2);                    //删除一个元素
    display(p);

    int i = 1;                          //查询一个元素
    int e1 = findelem_address(p,1);
    printf("查询链表的第%d个元素,值为%d\n",i,e1);

    int j = 5;                          //修改一个元素
    change(p,j,999);
    printf("修改链表的第%d个元素,现在的链表是:\n",j);
    display(p);

    mergelist(p,s);                     //合并两个链表
    display(p);

    insert(p,2,0);                      //插入一个元素
    display(p);

    sortlist(p);                        //链表排序
    display(p);

    node *q = gettail(p);               //指向最后一个节点的指针
    display(q);

    node *g = findmiddle(p);            //指向中间节点的指针
    display(g);

    /*
    circulationlist(p);                 //将单链表转换成循环链表
    display(p->next);
    */

    distory(p);
    distory(s);
    return 0;
}
发布了1 篇原创文章 · 获赞 1 · 访问量 21
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 数字20 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览