需要复习以下知识点
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;
}
}
未完待续哦 明天更新第二节 加油!!!!