链表基本概念
1.什么是链表
- 与数组相似,链表也是一种线性数据结构。
- 链表是一种逻辑顺序是连续的但物理存储单元上非连续、非顺序的存储结构。
在链表中,每个元素本身是一个单独的结构。
2.链表的类型
上图所示为单链表。还有种双向指向的双链表。引用力扣上的图:
本文重点介绍单链表。
3.链表的优缺点
与链表同为线性结构的数组相比起来有利有弊。
- 优点:操作简便,不需要知道具体位置,只需要知道附近的指针指向的地址。
- 缺点:创建复杂
单链表
1.初始化
链表是通过以结构体为节点,然后将所有节点通过结构体的指针域指向下一个节点连接起来并将数据存储到数据域中。
typedef struct node{
int data;//数据域
stryct node *next;//指针域
}Node,*Linklist;
//Node是结构体类型,Linklist是结构体指针类型
2.建立
有两种方法:尾插法和头插法。
尾插法:
思路
1.每次循环都新申请一个新指针pNew
,指向链表的最后一个节点。
2.令最后的pEnd->next
等于该节点的地址。
3.更改pEnd=pNew
,并使得pNew->next=NULL
。
代码实现如下:
pEnd->next=pNew;//将新节点同之前已链接好的尾节点链接起来
pEnd=pNew;//尾节指针移动指向新的尾节点
pNew->next=NULL;//结束循环后使尾节点指针域为NULL
头插法
思路
每次申请一个新指针,并插在头结点之后。
pNew->next=pHead->next;//将新节点与第二个连接
pHead->next=pNew;//将新节点与头节点连接
单链表的操作
1.单链表的遍历
思路
定义临时指针,并指向第一个节点。
void output(struct node *Head)
{
struct node *p=Head->next;
while(p!=NULL)
{
printf("%d\n",p->date);//输出
p=p->next;//指针移动
}
}
2.增加节点
思路
找到增加节点的上一个节点位置,改变其指向,来增加节点。
void insert(struct node *Head,int i)
{
int j=0;//控制循环
struct node*p=Head,*pNew;
while(j<i-1&&p)//找到目标节点的前一个节点位置
{
p=p->next;
j++;
}
if(p)
{
scanf("%d",p->val);//读入数据
s->next=p->next;//新节点指向原来的i节点
p->next=s;//新节点成为i节点
}
}
3.删除节点
思路
找到要删除的节点的上一个节点,定义一个指针指向待删除的节点,再链接要删除节点两边的节点。
void Delete(struct node *Head,int pos)
{
struct node *p=Head,*q;
int j=0;
while(j<pos-1&&p)
{
p=p->next;
j++;
}
if(p==NULL||p->next==NULL)
{
printf("ERROR");
}
else
{
q=p->next;//q指向第pos个节点
p->next=q->next;//链接删除节点两边的节点
free(q);//释放内存
}
}
4.修改节点
思路
遍历链表,找到对应节点修改数据域。
5.查找节点
思路
遍历链表,找到对应节点输出数据域即可。
习题
1.反转链表
题解:
用迭代的方法
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head){
struct ListNode*cur=head,*pre=NULL;
while(cur){
struct ListNode*tempnext=cur->next; //定义动态指针,储存正序下一节点
cur->next=pre;//正序下一节点指向上一节点
pre=cur;//讲=上一节点下移到当前节点
cur=tempnext;//动态指针指向当前节点
}
return pre;
}
2.回文链表
题解
用双指针方法,定义一个快指针,一个慢指针,快指针每次比慢指针多走一个节点,当快指针走到为尾节点结束,此时慢指针一定走在链表中间位置。然后将后半部分链表反转并与前链表比较。
bool isPalindrome(struct ListNode* head) {
if(head==NULL) return true;//判空
struct ListNode *fast,*slow,*p,*q=NULL;
fast=slow=head;
while(fast->next && fast->next->next){
fast=fast->next->next;
slow=slow->next;
}
slow=slow->next;
while(slow!=NULL){
p=slow;
slow=slow->next;
p->next=q;
q=p;
}
while(q!=NULL){
if(q->val!=head->val){
return false;
}
q=q->next;
head=head->next;
}
return true;
}