当前位置 : 主页 > 编程语言 > 其它开发 >

c语言链表实现

来源:互联网 收集:自由互联 发布时间:2022-05-30
这里我们来看看链表实现。 typedef int ElementType;typedef struct LNode { ElementType data; struct LNode* next;}LNode,*LinkedList; 首先是这个结构体,和顺序表类似。ElementType是之前的宏定义,你想要它是什

这里我们来看看链表实现。

typedef int ElementType;
typedef struct LNode {
    ElementType data;
    struct LNode* next;
}LNode,*LinkedList;

首先是这个结构体,和顺序表类似。ElementType是之前的宏定义,你想要它是什么类型他就是什么类型。之后就是这个Lnode指针。

或许你会好奇,欸这里为什么又给了一个指针,还是struct类型的,我们得回到链表的结构上面来讲。

链表一个节点分为两个数据域,不像顺序表,因此它的数据存储密度比起顺序表更低。你的一个节点存放了一个数据,然后,下一个数据域就是存放的地址,存放的下一个链表结点的地址,这个一定要主语,这个是链表的结构。

这里给了两个typedef后的名字,一个是Lnode,一个是*LinkedList。注意,第一个只是结构体名称,后面使用这个的时候用的是" . ",第二个是结构体指针,使用结构体指针访问结构体内容时使用的是"->"。

 

然后来看头插法建立链表。

我们这里先声明了一个结构体指针 s。

先来一手malloc 分配Lnode大小的空间,返回的指针强转为LinkedList指针类型,才可以赋值给L。

这个节点作为我们的头结点,如果不带头结点实现起来会稍显麻烦,我们后面再来看。头节点最开始是没有下一个结点的,所以头节点的next置NULL。

之后就是常规输入,我们又可以看到,又是一手malloc,不过这里是给了s,这个就是即将插入的新节点。这就是最开始初始化的s,其实这个LNode换成LinkedList也没什么问题。

申请到的空间给了s后,就把我们输入的值赋给s的data域。

然后就是最关键的操作了:

s->next = L->next;
把L的next域的值赋给s的next域,所以这里s就存了头节点原本的下一位的地址。
 L->next = s;
然后才是s的地址赋给L的next域。这样就完成了头插操作。这里别搞反了。
//头插法新建链表
LinkedList CreateList1(LinkedList& L) {`
    LNode* s;
    int x;
    L = (LinkedList)malloc(sizeof(LNode));//带头结点的链表,初始化头结点。
    L->next = NULL;//最开始的头结点没有下一个节点,置NULL。
    scanf_s("%d", &x);
     while (x!=9999){
        s = (LNode*)malloc(sizeof(LNode));
         s->data = x;//把读取到的值,给新空间中的data成员。
        s->next = L->next;
        L->next = s;
        scanf_s("%d", &x);
     }
    return L;

}

 

接下来:打印链表,这个比较简单。

//打印链表
void PrintList(LinkedList L) {
    L = L->next;//第一步跳出头指针。头指针是空的!
    while (L != NULL) {
        printf("%3d", L->data);//打印当前数据。
        L = L->next;//指向下一个节点
    } 
}

看看注释其实大概就差不多了,要注意的就是第一步必须跳出L头节点。

后面就是L=L->next指向下一个节点,然后依次打印。

 

之后就是尾插法,这个要注意,有一点点难。

//尾插法建立新链表
LinkedList CreateList2(LinkedList& L) {
    int x=0;
    LNode* s, * r = L;//LinkedList r ,s =L 结构体指针   r指向表尾节点.
    scanf("%d", &x);
    while (x != 9999) {
        s = (LNode*)malloc(sizeof(LNode));//即将添加进来的新节点。
        s->data = x;
        r->next = s;
        r = s;
        scanf("%d", &x);
    }
    r->next = NULL;//尾结点的next指针赋值为null。
    return L;

}

先设置s指针,供后续新节点的设置。后设置r指针,指向头节点。

之后就是基操,输入操作,新节点s的内存申请与赋值。

注意这个,

 r->next = s;//尾部节点指向新节点
这个时候r指向的其实是目前的尾部节点,它就可以直接用->运算符来直接操作当前的节点,当这一步完成了,他会直接:
r = s;
这个时候r指针就直接指向了新插入的节点,这样就保证了r指针始终指向最后一个节点。
r->next = NULL;
还有一步别忘了,r目前所指的节点的next域置为NULL,为后续插入做好准备。

接下来就是查找指定位置的元素。

//查找链表指定i位置的元素
LinkedList GetElem(LinkedList L, int i) {
    int j = 1;
    LinkedList p = L->next;//跳出头结点
    if (i == 0) {
        return L;//返回头节点
    }
    if (i < 1) {
        return NULL;//返回NULL。
    }
    while (p && j < i) {
        p = p->next;//p指向下一个节点。
        j++;
    }
    return p;



}

其实就是遍历加判断,用p=p->next来遍历,如果符合条件(p不为空&&j小于i),一位一位的往下找,最后return p即可。

 

按值查询:

 //按值查询
LinkedList LocateElem(LinkedList L, ElementType e) {
    LinkedList p = L->next;
    while (p != NULL&&p->data!=e) {
        p = p->next;
    }
    return p;
}

p!=null && p->data符合条件,就往下遍历,直到合适为止。

 

在第i个位置插入节点。

//在第i个位置插入节点
bool ListFrontInsert(LinkedList L, int i, ElementType e) {
    LinkedList p = GetElem(L, i - 1);//拿到要插入的位置的前一个节点的地址。
    if (p == NULL) {
        return false;
    }
    LinkedList s = (LNode*)malloc(sizeof(LNode));//新节点建立。
    s->data = e;
    s->next = p->next;
    p->next = s;
    return true;
}

参数列表里面传入的e就是我们想要插入的值,我们第一步是要拿到要插入的前一个结点的地址,如果这个是空的,那就别插了,说明他是第一个节点,没得搞,返回false。

然后就是基操,给s创建内存,把e赋值给它,

s->next = p->next:把要插入节点位置的前一个位置的next域所存的地址直接给s的next域,这个是不是和头插很相似?这就是头插为什么有个头结点会方便很多,这样插入操作就大大简化了。

p->next = s:要插入位置的前一个结点的next域存放s的地址。

至此,插入操作完成。

 

最后就是删除节点。

//删除节点
bool ListDelete(LinkedList L, int i) {
    LinkedList p = GetElem(L, i - 1);//查找删除元素的前驱结点。
    if (p == NULL) {
        return false;//要删除的位置不存在。
    }
    LinkedList q = p->next;
    p->next = q->next;
    free(q);//释放空间。
    q = NULL;
    return true; 

}

这里也是,先找到要删除元素前一个位置的节点,这样才好操作。如果p都没有,那就没得删了,返回false。

用一个q指针来存放p的下一个节点地址。其实就是你要删的节点。

然后把q->next赋值给p->next,这一步其实就是把q的下一个节点的地址直接给了p了,q就被没有直接引用了。

下一步就是用free函数把q毙了,删除操作结束。

避免野指针,可以把q置NULL。





 

上一篇:Minio的安装与使用
下一篇:没有了
网友评论