链表刷题-1 初步思考

发布于:2022-12-02 ⋅ 阅读:(803) ⋅ 点赞:(0)

 需要复习以下知识点

1单链表的基本概念

2.单链表-添加元素

3.单链表-删除元素

设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。

在链表类中实现这些功能:

1.get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。

2.addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。

3.addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。

4.addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。

5.deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

容易出现的一些问题:

1.内存的分配和释放

2.链表的遍历

3.第0个节点和最后一个节点怎么处理

4.怎样遍历链表才不会出现空指针异常

5.链表构造 怎样挂链

首先这里咋们复习下链表的定义:每一个节点需要一个值和一个指向下一个节点的next指针

在C语言里,struct结构体里,如果使用typedef的形式定义一个别名,如题目模板这样:

typedef struct {

} MyLinkedList;

如果在这个struct定义里面,直接把next指针定义为 MyLinkedList *next 就会报错 因为别名MyLinkedList是在结构体定义结束后才可以识别的一个别名; 所以在结构体里面,是不认识这个别名的。这是一个小坑。

那么正确的定义方法是什么?

typedef struct MyLinkedList_t{
	int val;
	struct MyLinkedList_t *next;
} MyLinkedList;

我们的解决方法是我们自己也规定一个struct的名字使得结构体里面可以直接用,那么在struct的里面,我就可以识别struct MyLinkedList_t这个结构体定义,成功地定义我们的next指针。

下面我们进入第一个重要环节:根据这个定义,构造一个链表。

MyLinkedList* myLinkedListCreate(){
    /*把我们的虚假链表头malloc出来之后它就是我们访问,管理链表的入口*/
    MyLinkedList *obj = (MyLinkList*)malloc(sizeof(MyLinkedList));
    /*对虚假链表头初始化 val随便是多少都可以 我们为了方便取0 以后也用不到了 next为null 此时真正的链表是空的*/
    obj->val = 0;
    obj->next = NULL;
    /*返回我们的链表入口*/
    return obj;
}

然后我们下一步要在链表里面增加节点

但是增加节点的时候我们要考虑两种情况 1.链表为空 2.链表不为空

//一 链表是空的
//举个例子
虚假的链表头  -> NULL
    obj     -> NULL(空链表)
    
呢么我们增加一个节点的过程如下:
    1.首先将节点初始化出来 也就是链表的第一个节点。
      我们得到一个节点Node 假设它的var是1 呢么next是NULL
    Node:
		var :1;
		next->NULL;
	2.把Node挂在链表头的后面,也就是链表的第一个节点
        虚假的链表头  -> 第一个节点 -> NULL
        obj -> Node(1) ->NULL(没有其他节点了)
        
//二 链表不是空的 
// 举个例子
虚假的链表头 -> 一串链表
obj  -> Node(5)  ->Node(6)
呢么我们增加一个节点的过程如下:
	1.首先将节点初始化出来 也就是链表的第一个节点。
      我们得到一个节点Node 假设它的var是1 呢么next是NULL
    Node:
		var :1;
		next->NULL;
	2.把Node的next 挂成我们已存在的链表
		原链表 通过obj -> next可以取到
	Node(1) -> Node(5) ->Node(6)
    3.把Node挂在链表头的后面 也就是把新链表挂在obj这个入口的后面
        虚假的链表头 -> 新链表
        obj -> Node(1) -> 原链表

代码实现

void myLinkedListAddAtHead(MyLinkedList* obj,int val){
    /*1-初始化节点*/
    MyLinkedList *Node = (MyLinkedList*)malloc(sizeof(MyLinkedList));
    Node->val = val;
    Node->next = NULL;
    /*2-分情况对待*/
    if(obj->next == NULL){
        /*如果原链表是空的 就直接把obj的next指向新节点*/
        obj ->next = Node;
        return;
    }else{
        /*如果原链表不是空的 我们就先把原链表挂在Node节点屁股后面*/
        Node->next = obj->next;
        /*再把新链表更新到obj这个入口上 也就是把新链表挂在obj虚拟节点的屁股后面*/
        obj->next = Node;
    }
}

                         ​​​​​​​        ​​​​​​​        ​​​​​​​        未完待续哦 明天更新第二节 加油!!!!


网站公告

今日签到

点亮在社区的每一天
去签到