单向链表的基本操作及常见面试题

一、单链表的基本操作 
1、初始化链表 
2、尾部插入 
3、尾部删除 
4、头部插入 
5、头部删除 
6、销毁链表 
7.打印单链表内容 
8、查询数据为d的节点 
9、获取单链表最后一个节点 
10、在指定位置之前插入一个节点 
11、指定位置节点删除 
12、删除数据为d,第一次出现的节点 
13、删除数据为d的所有节点 
14、创建新节点
二,链表常见面试题 
1、删除指定位置的非尾节点 
2、获取链表长度
3、逆序打印单链表
4、在无头单链表的一个节点前插入一个节点
5、单链表实现约瑟夫环
6、逆置单链表
7、单链表排序
8、合并两个单链表
9、找单链表中间节点,只能遍历一次链表
10、找单链表的倒数第k个节点,只能遍历一次链表
11、判断单链表是否带环
12、求有环链表中环的长度
13、求带环单链表环的入口
14、判断两个不带环的单链表是否相交,若相交,返回交点,若不想交,返回NULL
15、判断两个带环的单链表是否相交,若相交,返回交点,若不想交,返回NULL 
16、复制复杂链表
17、求两个已排好序的单链表中的相同数据
18、删除倒数第k个节点

头文件 LinkList.h :

#ifndef __LINKLIST_H__
#define __LINKLIST_H__

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

typedef int DataType;

typedef struct NODE
{
    DataType _data;//数据域
    struct NODE *_pNext;//指针域,指向下一个节点
}Node, pList;

typedef struct CSLinkList //复杂链表,比正常链表多一个随机指针域,指向任意位置
{
    DataType _data;
    struct CSLinkList *_random;
    struct CSLinkList *_next;
}CSLinkList;

void InitLinkList(pList **pHead);//初始化链表
pList* BuyNode(DataType d)//创建新节点

void PushBack (pList **pHead, DataType d);//尾部插入

void PopBack (pList **pHead);//尾部删除

void PushFront (pList **pHead, DataType d);//头部插入

void PopFront (pList **pHead);//头部删除

void DestroyLInkLIst (pList **pHead);//销毁链表

void PrintLinkList (pList *pHead);//打印单链表内容

Node* FindNode (pList *pHead, DataType d);//查找数据为d节点

Node* LinkListBack(pList* pHead);// 获取单链表最后一个节点 

void Insert (pList **pHead, Node* pos, DataType d);//在指定位置之前插入一个值 

void Erase (pList **pHead, Node *pos);//指定位置删除

void Remove (pList **pHead, DataType d);//删除数据d第一次出现的节点

void RemoveAll (pList **pHead, DataType d);//删除出现指定元素的所有节点
void EraseNotTailNode (Node *pos);//删除指定位置的非尾节点

int GetLength (pList *pHead);//获取链表长度

void PrintLinkListFromTailToHead (pList *pHead);//逆序打印单链表

void InsertWithoutHead (Node *pos, DataType d);//在无头单链表的一个节点前插入一个节点

Node* JosephCircle (pList **pHead, int k);//单链表实现约瑟夫环

void Reverse(pList **pHead);//逆置单链表

void LinkListSort (pList **pHead);//单链表排序

Node *MergerLinkList (pList *pHead1, pList *pHead2);//合并两个单链表

Node* FindMiddleNode (pList *pHead);//找单链表中间节点,只能遍历一次链表

Node* FindLastKNode (pList *pHead, int k);//找单链表的倒数第k个节点,只能遍历一次链表

Node* LinkListHaveCircle(pList *pHead);//判断单链表是否带环

int LinkListWithCircleLen (pList *pHead);//求有环链表中环的长度

Node *CircleEntrance (pList *pHead);    //求带环单链表环的入口

Node *IsListintersect (pList *pHead1, pList* pHead2);//判断两个不带环的单链表是否相交,若相交,返回交点,若不想交,返回NULL

Node *IsListintersectWithCircle (pList *pHead1, pList* pHead2);//判断两个带环的单链表是否相交,若相交,返回交点,若不想交,返回NULL

CSLinkList *CopyComplexLinkList (CSLinkList *PHead);//复制复杂链表

void UnionSet(Node *li, Node *l2);//求两个已排好序的单链表中的相同数据

void DeleteLastKNode (pList **pHead, int k);//删除倒数第k个节点

#endif

实现过程(main.c文件):

一、链表基本操作:

1、链表初始化

void InitLinkList(pList **pHead)//初始化链表,数据域为0,指针域为空
{
    pList *cur = NULL;
    assert (pHead != NULL);//传来的地址不能为空

    cur =(pList *) malloc (sizeof (pList));

    if (NULL == cur)//开辟空间失败,程序结束
    {
        perror ("InitLinkList::malloc>>");
        exit (1);
    }
    (*pHead) = cur;
    (*pHead)->_data = 0;
    (*pHead)->_pNext = NULL;
}

2、创建新节点:

pList* BuyNode(DataType d)//创建新节点
{
    pList *NewNode = (pList *)malloc (sizeof (pList));
    if (NewNode == NULL)
    {
        perror ("BuyNode :: malloc>>");
        system ("pause");
        exit (1);
        return NULL;
    }
    NewNode->_data = d;
    NewNode->_pNext = NULL;
    return NewNode;
}

3、尾部插入

void PushBack(pList **pHead, DataType d)//尾部插入
{
    pList *cur = *pHead;
    assert (pHead != NULL);//传入的地址不为空
    //1.链表为空
    if (*pHead == NULL)
    {
        *pHead = BuyNode (d);
    }
    //2.链表不为空
    else 
    {
        while (cur->_pNext != NULL)
        {
            cur = cur->_pNext;//找最后一个节点
        }
        cur->_pNext = BuyNode(d);
    }
}

4、尾部删除

void PopBack (pList **pHead)//尾部删除
{
    if (*pHead == NULL)//链表为空
    {
        printf ("链表为空,无法删除!!\n");
        return;
    }
    else if ((*pHead)->_pNext == NULL)//链表只有一个节点
    {
        pList *cur = *pHead;
        free (cur);
        cur = NULL;
        (*pHead) = NULL;
        return;
    }
    else//链表有多个节点
    {
        pList *cur = *pHead;
        pList *pre = NULL;
        while (cur->_pNext)
        {
            pre = cur;
            cur = cur->_pNext;
        }
        pre ->_pNext = NULL;
        free (cur);
        cur = NULL;
    }
}

5、头部插入

void PushFront (pList **pHead, DataType d)//头部插入
{
    pList *cur = BuyNode (d);
    assert (pHead);

    cur ->_pNext = (*pHead);
    (*pHead) = cur;
}

6、头部删除

void PopFront (pList **pHead)//头部删除
{
    if (*pHead == NULL)//链表为空
    {
        printf ("链表为空,无法删除!!\n");
        return;
    }
    else
    {
        pList *cur = *pHead;
        *pHead = (*pHead)->_pNext;
        free (cur);
        cur = NULL;
    }

}

7、打印单链表内容

void PrintLinkList (pList *pHead)//打印单链表内容
{
    pList *cur = pHead;
    while (cur)
    {
        printf ("%d -> ", cur->_data);
        cur = cur ->_pNext;
    }
    printf ("NULL\n\n");
}

8、销毁单链表

void DestroyLInkLIst(pList **pHead)//销毁链表
{
    pList *cur = (*pHead);
    pList *pre = NULL;

    assert (pHead != NULL);//传来的地址不能为空

    while (NULL != cur)
    {
        pre = cur;
        cur = cur->_pNext;
        free (pre);
        pre = NULL;
    }
    (*pHead) = NULL;
    printf ("链表销毁成功!!\n");
}

9、查找数据为d节点,返回该节点地址;如果没有该节点返回空

Node* FindNode (pList *pHead, DataType d)//查找数据为d节点,返回该节点地址;如果没有该节点返回空
{
    pList *cur = pHead;
    if (NULL == pHead)//链表为空,直接返回NULL
    {
        return NULL;
    }

    while (cur)//寻找数据域为 d 的节点,找到了直接返回该节点
    {
        if (d == cur->_data)
        {
            return cur;
        }
        cur = cur->_pNext;
    }

    return NULL;//如果链表都遍历完都找不到返回NULL
}

10、获取单链表最后一个节点

Node* LinkListBack(pList* pHead)
{
    Node* pPreCur = NULL;
    Node* pCur = pHead;
    while(pCur)
    {
        pPreCur = pCur;
        pCur = pCur->_pNext;
    }

    return pPreCur;
}

11、 在指定位置之前插入一个值

void Insert (pList **pHead, Node* pos, DataType d)//在指定位置之前插入一个值
{
    pList *cur = *pHead;     //用来寻找指定位置
    pList *pre = NULL;       //用来标记指定位置的前一个位置
    pList *new_node = NULL;  //要插入的新节点

    assert (pHead != NULL && pos != NULL);

    if (*pHead == NULL)
    {
        printf ("链表为空,插入失败!!\n");
        return;
    }

    if  (pos == *pHead)   //如果给定插入位置为第一个节点
    {
        new_node = BuyNode (d);
        new_node ->_pNext = *pHead;
        *pHead = new_node;
    }
    else    //如果指定插入位置不是第一个节点
    {
        while (cur)
        {
            if (cur == pos)
            {
                new_node = BuyNode (d);
                pre ->_pNext = new_node;
                new_node ->_pNext =
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值