文章目录
单链表
理解C语言里是如何构造出链表的(初始化代码可以补基础)
口述过程:
链表是一种数据结构,由一个头结点,头指针和多个结点构成。
结点的数据类型:。
一般来说,一个结点包含数据域和指针域,分别用来存储数据和指出上下文。
结点和链表初始化代码:
//自定义
typedef struct linkedlist{
ElementType e; //数据域
struct linkedlist * next; //指针域
};
//Leetcode 定义一般如下
struct ListNode{
int val; //data
struct ListNode *next; //pointer
}
有了结点类型,距离创建一个普通单链表,还需要头指针和头结点
并且在初始化函数中,我们需要返回一个指向新链表的头指针。
因此是指针函数。参数为空
初始化函数代码如下:
struct ListNode * initLink()
{
int i=0;
struct ListNode * p = null;
struct ListNode * temp = (struct ListNode *)malloc(sizeof(struct ListNode) )
p = temp ;
for(i = 1 ; i < 5 ; i++)
{
struct ListNode * a = (struct ListNode *)malloc(sizeof(struct ListNode) );
a->val= i;
a->next = null;
temp->next = a;
temp = temp->next;
}
/*
这一段循环代码详解:
首先,为了构造链表,我们需要在每一次循环中创建一个新结点,并且给它赋值,但是如果不创建一个结点指针指向一块分配好的内存空间,新节点就会在一次循环完成后就会丢失。所以为什么要建立结点指针就是这个原因,而指向头结点的指针temp相对于循环是一个全局变量,因此我们可以用temp进行遍历,而真正的指向头结点的指针head不动,用来返回整个链表。因为只要有指针,我们就能找到这样逻辑连续的链表空间,遍历中改变temp指针的指向并不会对头指针造成影响
*/
return p;
}
增加元素
首部添加元素
口述过程:
创建一个结点,新结点通过头指针指向头结点,头指针指向新结点
结果:返回头指针
中间添加元素
口述过程:
首先,通过一个指针遍历到当前位置
在这个位置中,我们需要通过插入位置上一个结点找到下一个结点,便于添加新结点指针域,所以我们遍历到上一个结点可以停止。
此时,我们将新节点指向下一个节点,然后再把前驱节点指向该节点
结果:返回头指针
尾部添加元素
口述过程:
尾部添加元素很简单,将最后一个结点后驱指向新节点,然后新节点指null(如果没有指的话)
结果:返回头指针
单链表增加元素操作代码汇总(以顺序链表为例)
struct ListNode * insertNode(struct ListNode * head,struct ListNode * nodeInsert ,int position)
{
//首部添加结点
int size = getLength(head);
if(position>size+1 || position < 1)
return head;
if(head==null)
return nodeInsert;
if(position==1)
{
nodeInsert->next = head;
head = nodeInsert;
return head;
}
//中间添加结点
int count =1;
struct ListNode * p = head;
while ( count < position-1 )
{
p = p->next;
count++;
}
nodeInsert->next = p->next;
p->next = nodeInsert;
return head;
}
删除结点
删除头结点
口述过程:将头指针指向头结点下一个节点,释放头结点。
结果:返回头指针
删除最后一个节点
口述过程:将倒数第二个结点指向空。
结果:返回头指针
删除中间节点
口述过程:将上一个节点指向中间结点的下一个节点,然后,将中间节点释放
结果:返回头指针
代码汇总
struct ListNode * deletNode (struct ListNode * head,int position)
{
## delet head node
int size = getLength(head);
if(head==null)
return NULL;
if(position > size || position < 1 )
{
return head;
}
if(postion == 1)
{ struct ListNode * curNode = head;
head = head->next;
free(curNode);
return head;
}else{
int count =1;
struct ListNode * curNode = head;
while(count<postion -1)
{
curNode = curNode->next;
count++;
}
struct ListNode *mid = curNode->next;
curNode->next=curNode->next->next;
//新建mid指针,指向中间节点,不然释放不了
free(mid);
return head;
}
}
遍历单链表
口述过程:新建头指针,循环结束条件:p->next==null | p
!=null
结果:打印链表中的值或者获得链表长度
PS:就算不需要返回头指针,也要注意头指针归零或者直接用虚拟指针遍历链表
代码:
void printList(struct ListNode * head)
{
struct ListNode * p =head;
while(p)
{
printf("%d ",p->val);
printf(",");
p=p->next
}
}
int getLinkLength(struct ListNode * head)
{
int length = 0 ;
struct ListNode * p = head;
while(p)
{
length++;
p=p->next;
)
return length;
}
双向链表(部分过程简化)
构建
口述过程:双向链表结构很简单,多了一个前驱节点。
那么在初始化操作中先找后继在找前驱。
代码:
typedef struct listNode{
ElementType e;
struct listNode * up;
struct listNode * down;
}ListNode;
struct ListNode * initdLink()
{
int i;
//创建头指针
struct ListNode * head = null;
//创建头结点
struct ListNode * temp = (struct ListNode *)malloc(sizeof(struct ListNode));
temp->e = 0;
temp->up=null;
temp->down =null;
p=temp;
for(i =0; i< 6 ;i++)
{
struct ListNode * q = (struct ListNode *)malloc(sizeof(struct ListNode));
q->e = i;
q->up = null;
temp-> down = q;
q->up =temp;
temp=temp->down//q
}
return head
}
增删
已知上一个节点位置,该结点位置。
增加一个节点:
口述过程:双向链表由于有前驱和后继,因此我们需要有一定顺序。
比如:先解决后继,再解决前驱。该节点后继指向上一个结点的后继,上一个节点后继指向该节点,该节点的后继指向该节点,该节点的前驱指向上一个节点
代码:
struct ListNode * insertNode(struct ListNode * head,struct ListNode * nodeInsert ,int position)
{
//首部添加结点
int size = getLength(head);
if(position>size+1 || position < 1)
return head;
if(head==null)
return nodeInsert;
if(position==1)
{
nodeInsert->next = head;
head->cur=nodeInsert
head = nodeInsert;
return head;
}
//中间添加结点
int count =1;
struct ListNode * p = head;
while ( count < position-1 )
{
p = p->next;
count++;
}
nodeInsert->next = p->next;
nodeInsert->cur=p;
nodeInsert->next->cur=nodeInsert;
return head;
}
struct ListNode * deletNode (struct ListNode * head,int position)
{
## delet head node
int size = getLength(head);
if(head==null)
return NULL;
if(position > size || position < 1 )
{
return head;
}
if(postion == 1)
{
struct ListNode * curNode = head;
head = head->next;
head->next->cur=head;
free(curNode);
return head;
}else{
int count =1;
struct ListNode * curNode = head;
while(count<postion -1)
{
curNode = curNode->next;
count++;
}
struct ListNode *mid = curNode->next;
curNode->next=curNode->next->next;
mid->next->cur = curNode;
//新建mid指针,指向中间节点,不然释放不了
free(mid);
return head;
}
}