【数据结构】【单链表】

1.单链表

1.1 单链表的创建
typedef struct LNode
{
    int data;
    struct LNode* next;
}LNode, * LinkList;
1.2单链表的初始化
int InitLinkList(LinkList *L) 
{
    *L = (LinkList)malloc(sizeof(LNode));//为头结点分配空间
    if (*L == NULL)
    {
        printf("开辟内存空间失败,初始化头结点失败");
        return -1;
    }
    (*L)->next = NULL;
    return 0;
}
1.3打印单链表
int printLinkList(LinkList *L) {
    LNode* p = *L; //p为指向当前结点的指针
    //判断链表是否为空
    if (p->next == NULL) {
        printf("该链表为空");
        return -1;
    }
    while (p->next!=NULL)
    {
        p = p->next;//跳过头结点
        printf("%d ",p->data);
    }
    return 0;
}
1.4头插建立单链表
1.4.1 原理图

注意: 原理图中的代码表示和代码并不对应

在这里插入图片描述

1.4.2代码
int headInsert(LinkList* L, int n)
{
    LNode* p = *L;
    LNode* pnew = NULL;//新的节点
    for (int i = 0; i < n; i++)
    {
        pnew = (LinkList)malloc(sizeof(LNode));
        if (pnew == NULL)
        {
            printf("error");
            return -1;
        }
        int num = 0;
        printf("请输入:");
        scanf("%d", &num);
        pnew->data = num;//将数据插入到新的节点中
        pnew->next = (*L)->next;//新的节点的指针域指向头结点的下一个结点
        (*L)->next = pnew;//头结点指针域指向新的结点
    }
    return 0;
}
1.4.3测试头插
int main() {
    //定义并初始化单链表
    LinkList p = NULL;
    //初始化单链表
    InitLinkList(&p);
    int n = 5;//插入元素个数
    headInsert(&p, n);//头插
    printLinkList(&p);//打印单链表中的元素
    return 0;
}
1.4.4运行结果

在这里插入图片描述

1.5 头删
1.5.1原理

在这里插入图片描述

1.5.2代码
int delHead(LinkList* L)
{
    LNode* pdel = NULL;//存储删除结点
    //首先对表进行判空
    if ((*L)->next == NULL)
    {
        printf("空表不能删除");
        return -1;
    }
    
    pdel = (*L)->next;//要删除的结点
    (*L)->next = pdel->next;//令头结点的next指向要删除的结点的下一个节点
    free(pdel);//释放删除结点的内存
    return 0;
}
1.5.3测试头删
int main() {
    //定义并初始化单链表
    LinkList p = NULL;
    //初始化单链表
    InitLinkList(&p);
    int n = 5;//插入元素个数
    headInsert(&p, n);//头插
    printf("头删前单链表元素:\n");
	printLinkList(&p);
	delHead(&p);//头删
	printf("\n头删后单链表元素:\n");
    printLinkList(&p);
    return 0;
}
1.5.4运行结果

在这里插入图片描述

1.6尾插建立单链表
1.6.1原理图

在这里插入图片描述

由图可知,尾插每一次都把新的结点插入到单链表的最后

1.6.2代码
int InsertLinkListTail(LinkList* L,int n)
{
    LNode* pnew = NULL;
    LNode* ptail = *L;
    for (int i = 0; i < n; i++)
    {
        pnew = (LinkList)malloc(sizeof(LNode));
        if (pnew == NULL)
        {
            printf("error");
            return -1;
        }
        int num = 0;
        printf("请输入:");
        scanf("%d", &num);
        pnew->data = num;
        pnew->next = NULL;
        ptail->next = pnew;
        ptail = pnew;//尾节点后移
    }
    return 0;
}
1.6.3测试代码
int main() {
    //定义并初始化单链表
    LinkList p = NULL;
    //初始化单链表
    InitLinkList(&p);
    int n = 5;//插入元素个数
    InsertLinkListTail(&p, n);//尾插
    printLinkList(&p);
    return 0;
}
1.6.4运行结果

在这里插入图片描述

1.7尾删

尾删是每一次删除单链表的最后一个结点

1.7.1原理图

在这里插入图片描述

1.7.2代码
int delTail(LinkList* L)
{
    //LNode* p = *L;
    LNode* tail = *L;//指向头结点
    if (tail == NULL)
    {
        printf("错误");
        return -1;
    }
    LNode* pre = NULL;
    while (tail->next!=NULL)
    {
        pre = tail;//循环结束后指向尾结点前一个结点
        tail = tail->next;//指向尾结点
    }
    pre->next = NULL;//删除尾节点
    free(tail);//释放尾节点空间
    return 0;
}
1.7.3测试代码
int main() {
    //定义并初始化单链表
    LinkList p = NULL;
    //初始化单链表
    InitLinkList(&p);
    //尾插法插入10个节点
    int n = 5;//插入元素个数
    InsertLinkListTail(&p, n);//尾插建立单链表
    printf("尾删前单链表元素:");
    printLinkList(&p);
    delTail(&p);//尾删
    printf("\n尾删后单链表元素:");
    printLinkList(&p);
    return 0;
}
1.7.4运行结果

在这里插入图片描述

运行结果可知,尾节点被删除了

1.8插入结点(按位置插入)

在单链表任意位置插入一个结点

1.8.1原理图

在这里插入图片描述

1.8.2代码
int insertNode(LinkList *L,int i,int e)
{
    //判断插入位置是否合法
    if (i < 1)
        return -1;
    LNode* p = *L; //p为指向当前结点的指针
    int j = 0; //p指针指向的当前结点,当前位置为头结点
    //寻找i-1个节点
    while (p != NULL && j < i - 1) {
        p = p->next;
        j++;
    }
    LNode* s = (LNode*)malloc(sizeof(LNode));  //创建新结点
    if (s == NULL)
    {
        return -1;
    }
    s->data = e;
    s->next = p->next;
    p->next = s;
    return 0;
}
1.8.3测试代码
int main() {
    //定义并初始化单链表
    LinkList p = NULL;
    //初始化单链表
    InitLinkList(&p);
    //尾插法插入5个节点
    int n = 5;//插入元素个数
    InsertLinkListTail(&p, n);//尾插建立单链表
    printf("插入结点前单链表元素:");
    printLinkList(&p);
    //在p中第i个元素之前插入数据元素e 
    insertNode(&p, 5, 66);
    printf("\n插入结点后单链表元素:");
    printLinkList(&p);
    return 0;
}
1.8.4运行结果

在这里插入图片描述

1.9删除结点

删除单链表中任意位置的结点

1.9.1原理图

在这里插入图片描述

1.9.2代码
//删除链表中某个位置的元素
int DeleteList(LinkList* L, int i, int* temp)
{
    LNode* pre,*p; //pre指向被删除结点的前一个结点,p指向被删除节点
    pre = *L;
    int j = 0;
    //查找第i-1个节点
    while (pre != NULL && j < i-1) {
        pre = pre->next;
        j++;
    }
    //判断删除位置是否合法
    if (pre->next==NULL || j > i - 1)
    {
        printf("删除位置不合理!!");
        return -1;
    }
    p = pre->next;
    pre->next = p->next; 	//改变删除结点前驱结点的指针域 
    *temp = p->data;//删除结点的数据域中的数据存放在temp中
    free(p);//释放删除结点的空间 
    return 0;
}
1.9.3测试代码
int main() {
    //定义并初始化单链表
    LinkList p = NULL;
    //初始化单链表
    InitLinkList(&p);
    //尾插法插入5个节点
    int n = 5;//插入元素个数
    InsertLinkListTail(&p, n);//尾插建立单链表
    printf("删除结点前单链表元素:");
    printLinkList(&p);
    int delEle = 3;//删除第几个元素
    int temp = 0;//用于存储删除元素
    DeleteList(&p, delEle, &temp);
    printf("\n删除第%d个位置的元素为:%d\n", delEle, temp);
    printf("删除结点后单链表元素:");
    printLinkList(&p);
    return 0;
}
1.9.4运行结果

在这里插入图片描述

2.0按位置查找元素
2.0.1代码
//获取链表中的某一个位置的元素
int GetElem(LinkList* L, int i, int* e)
{
    LNode* p = *L; //p指针用于指向链表的首结点
    int length = ListLength(L);//表长
    if(i<1||i>length)
    {
        printf("查找位置不合法");
        return -1;
    }
    int j = 0;
    //查找第七个元素,下标为6,所以让p指针指向下表为6的结点
    while (p != NULL && j < i) {
        p = p->next;
        j++;
    }
    //当前结点的数据域中就是所要查找的元素
    *e = p->data;
    return 0;
}
2.0.2测试代码
int main() {
    //定义并初始化单链表
    LinkList p = NULL;
    //初始化单链表
    InitLinkList(&p);
    //尾插法插入7个节点
    int n = 7;//插入元素个数
    InsertLinkListTail(&p, n);//尾插建立单链表
    printf("单链表中的元素:");
    printLinkList(&p);
    //查找元素(查找第七个位置的元素,并把元素存在变量e中)
    int e = 0;//用于接收查找到的数据
    int i = 4;//查找第几个位置的元素
    GetElem(&p, i, &e);
    printf("\n第%d个位置的元素为:%d",i,e);
    return 0;
}
2.0.3运行结果

在这里插入图片描述

2.1按值查找元素
2.1.1代码
//按照值查找
int locatePos(LinkList* L, int e)
{
    LNode* p = *L;//指向头结点
    int i = 0;
    int temp = 0;
    //从头结点开始查找
    while (p!=NULL)
    {
        //找到e后
        if (p->data == e)
        {
            printf("找到了%d元素,是第%d个元素",e,i);
            temp = p->data;
        }
        //未找到e
        i++;//因为有首结点,所以i的值就是第几个位置
        p = p->next;//指针移动到下一个节点
    }
    if (temp != e)
    {
        printf("未找到%d元素",e);
    }
}
2.1.2测试代码
int main() {
    //定义并初始化单链表
    LinkList p = NULL;
    //初始化单链表
    InitLinkList(&p);
    //尾插法插入7个节点
    int n = 7;//插入元素个数
    InsertLinkListTail(&p, n);//尾插建立单链表
    printf("单链表中的元素:");
    printLinkList(&p);
    locatePos(&p, 5);//查找为5的元素(按值查找)
    return 0;
}
2.1.3运行结果

在这里插入图片描述

2.2求链表的长度
2.2.1代码
int ListLength(LinkList* L)
{
    LNode* p = *L; //p指针用于指向链表的首结点
    int LinkListlegth = 0;
    while (p->next != NULL)
    {
        p = p->next;
        LinkListlegth++;
    }
    return LinkListlegth;
}
2.2.2测试代码
int main() {
    //定义并初始化单链表
    LinkList p = NULL;
    //初始化单链表
    InitLinkList(&p);
    //尾插法插入7个节点
    int n = 7;//插入元素个数
    InsertLinkListTail(&p, n);//尾插建立单链表
    //打印节点元素
    printf("单链表中的元素:");
    printLinkList(&p);
    //求链表的长度
    int length = ListLength(&p);
    printf("\n链表长度为:%d\n", length);
    return 0;
}
2.2.3运行结果

在这里插入图片描述

2.3销毁链表

先删除 除了头结点之外的结点,最后把头结点删除

2.3.1代码

这里我使用了无限头删的方法清空单链表,最后把头结点删除,为了测试出结果我把删除头结点的操作注释了

//销毁链表
int destoryLinkList(LinkList* L)
{
    LNode* p = *L;
    LNode* q = NULL;
    while (p->next != NULL)
    {
        q = p->next;
        p->next = q->next;
        free(q);
    }
    //干掉头结点,这里我为了测试就先不删除头结点了
    //free(*L);
    return 0;
}
2.3.2测试代码
int main() {
    //定义并初始化单链表
    LinkList p = NULL;
    //初始化单链表
    InitLinkList(&p);
    //尾插法插入7个节点
    int n = 7;//插入元素个数
    InsertLinkListTail(&p, n);//尾插建立单链表
    printf("销毁前单链表中的元素:");
    printLinkList(&p);
    destoryLinkList(&p);
    printf("\n销毁后单链表中的元素:");//为了测试没有删除头结点
    printLinkList(&p);
    return 0;
}
2.3.3运行结果

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值