zoukankan      html  css  js  c++  java
  • 单链表的初始化,整表创建,单个元素插入,单个元素删除,整表删除等操作

          很早之前学的数据结构,放了很久后,以致对里面的一些操作都有些遗忘,故而再次温习了一下数据结构,并整理了一点儿笔记,放在这里和大家分享, 我的代码注释的已经很详细了,对于容易出错的地方我也都有标注,欢迎大家交流。

    #include "stdafx.h"
    #include <stdio.h>
    #include <malloc.h>
    #include <stdlib.h>
    #include <time.h>
    #define OK 1
    #define ERROR 0
    
    //#define 
    typedef int Status;//函数返回的状态值类型
    typedef int ElemType;
    typedef struct Node
    {
        ElemType data;
        struct Node *next;
    } Node;//定义一个单链表存储结构
    
    typedef struct Node *LinkList;//定义一个线性表,定义的是Node结构体的指针
    
    //创建一个具有n个元素的单链线性表,采用头插法创建,注意:其中已经包含了初始化操作
    //初始化链表,函数调用完毕后,L会指向一个空的链表,即会改变指针的值,所以要用*L
    //*L表示结构体指针的指针
    Status List_Link_Create(LinkList *L,int n)//头插法
    {
        LinkList p;
        *L =(LinkList) malloc(sizeof(Node));//产生一个头结点,并使得*L指向这个头结点,于是*L便是一个头指针,头指针是链表的必要元素
        if (L == NULL)
            return ERROR;
        (*L)->next = NULL;//使得头指针指向的内容为空,建立一个带头结点的单链表
        printf("请输出n个随机生成的数字:");
        for (int i = 0; i < n; i++)
        {
            p = (LinkList)malloc(sizeof(Node));//生成新节点
            p->data = rand() % 100 + 1;//随机生成100以内的数字
            printf("%d", p->data);
            printf(" ");//字符与字符之间空格
            
            p->next = (*L)->next;
            (*L)->next = p;//插入到表头
        }
        printf("
    ");//换行
        return OK;
    }
    
    Status List_Link_Length(LinkList L)//求出单链表的长度
    {
        int j = 0;
        LinkList p;
        p = L;
        while (p != NULL)
        {
            p = p->next;
            j++;
        }
        printf("单链表当前的长度=%d",j);
        return j;
    }
    //Status List_Link_Ini(LinkList L)//初始化一个线性单链表
    //{
    //    L = (LinkList)malloc(sizeof(Node));//产生一个头结点,并使得L指向这个头结点,于是L便是一个头指针,头指针是链表的必要元素
    //    if (L == NULL)
    //        return ERROR;
    //    L->next = NULL;//使得头结点的指针域为空
    //    return OK;
    //}
    
    //销毁链表L,释放链表L申请的内存,使L的值重新变为NULL,所以会改变L的值,得用*L
    Status List_Link_Destory(LinkList *L)
    {
        LinkList p,q;
        p = (*L)->next;
        while (p)
        {
            q = p->next;
            free(p);
            p = q;
        }
        (*L)->next = NULL;//头节点的指针域为空
        return OK;
    }
    
    Status List_Link_Insert(LinkList *L, int i, ElemType e)//在L中第i个元素之前插入新的数据元素e
    {
        int j;
        LinkList p, s;
        p = *L;
        j = 1;
        while (p&&j<i)//遍历寻找第i个节点
        {
            p = p->next;
            ++j;
        }
        if (!p || j > i)
            return ERROR;//第i个元素不存在
        s = (LinkList)malloc(sizeof(Node));//生成一个新节点
        s->data = e;
        s->next = p->next;//将p的后继节点赋值给s的后继
        p->next = s;
        printf("插入节点的元素的值为:%d
    ", e);
        return OK;//插入成功
    
    }
    
    //删除L的第i个数据元素,并用e返回其值
    //注意这里是*e,而不是e,区别于插入当中的变量e
    Status List_Link_Delete(LinkList *L, int i, ElemType *e)
    {
        int j=1;
        LinkList p, q;
        p = *L;
        while (p->next&&j<i)//遍历寻找第i个元素
        {
            p = p->next;
            ++j;
        }
        if (!(p->next) || j > i)
            return ERROR;//第i个元素不存在
    
        q = p->next;//q表示即将被删除元素的节点
        *e = q->data;
        p->next = q->next;//将q    后继赋值给p的后继
        free(q);//q被利用完毕后,将q释放
        printf("删除第%d个节点的元素值为:%d
    ", i, *e);
        return OK;
    
    }
    
    Status List_Link_GetElem(LinkList L, int i, ElemType *e)//取出单链表L中的第i个元素,并通过*e返回
    {
        int j;
        LinkList p;
        p = L->next;//找到单链表L中第一个节点
        j = 1;
        while (p&&j < i)
        {
            p = p->next;
            ++j;
        }
        if (!p || j > i)
            return ERROR;//第i个元素不存在
        
        *e = p->data;//取出第i个元素的数据域并传值给*e
        printf("被取出的元素的值为:");
        printf("%d
    ", *e);
        return OK;
    }
    int main()//测试函数
    {
        LinkList L1;
        ElemType f,h;
        List_Link_Create(&L1, 6);
        List_Link_GetElem(L1, 3, &f);
        List_Link_Insert(&L1, 3, 15);//在链表的第3个节点之前插入元素15
        List_Link_Delete(&L1, 3, &h);//删除链表的第3个节点的元素,并返回给h输出
        return OK;
    }
    
    
    
    
    
    
    
    
    
    /*1.对于LinkList L : L是指向定义的node结构体的指针, 可以用->运算符来访问结构体成员, 即L->elem, 而(*L)就是个Node型的结构体了,
    可以用点运算符访问该结构体成员, 即(*L).elem;
    
    2.对于LinkList *L:L是指向定义的Node结构体指针的指针, 所以(*L)是指向Node结构体的指针, 
    可以用->运算符来访问结构体成员, 即(*L)->elem, 当然, (**L)就是Node型结构体了, 所以可以用点运算符来访问结构体成员, 即(**L).elem;
    
    3.在链表操作中, 我们常常要用链表变量作物函数的参数, 这时, 用LinkList L还是LinkList *L就很值得考虑深究了, 
    一个用不好, 函数就会出现逻辑错误, 其准则是:如果函数会改变指针L的值, 而你希望函数结束调用后保存L的值, 那你就要用LinkList *L, 
    这样, 向函数传递的就是指针的地址, 结束调用后, 自然就可以去改变指针的值;而如果函数只会修改指针所指向的内容,
    而不会更改指针的值, 那么用LinkList L就行了;*/


    下面是我在vs2013中的测试结果:

    请输出n个随机生成的数字:42 68 35 1 70 25
    被取出的元素的值为:1
    插入节点的元素的值为:15
    删除第3个节点的元素值为:15
    请按任意键继续. . .

  • 相关阅读:
    记录移动端原生开发基础样式
    windows关闭打开应用的时候的安全弹窗
    thinkPad触控板手势安装
    git修改账号密码
    ssh免密登录失效处理
    xxl-rpc remoting error(Connection refused (Connection refused)), for url : http://xxxxxx:19997/run
    utools好用插件分享
    Android Studio打包apk闪退处理
    maven下载jar包失败处理
    微信文件下载位置
  • 原文地址:https://www.cnblogs.com/huster666/p/5642638.html
Copyright © 2011-2022 走看看