一.单向链表(带头节点)的任意位置插入,代码实现
- 定义链表的节点和表头
cpp
//定义节点(链表的核心)
typedef int Element;
typedef struct list_node{
Element value;
struct list_node *next;
}ListNode;
//链表的表头
typedef struct{
ListNode head;
int len;
}LinkList;
2.创建链表及初始化
cpp
#include<stdlib.h> //申请堆空间要用到的头文件
LinkList *createLinkList(){
LinkList *linklist=(LinkList*)malloc(sizeof(LinkList)); //申请堆空间
if(linklist==NULL){
return NULL; //如果空,则返回NULL,停止执行下面的指令
}
//初始化
linklist->len=0;
linklist->head.value=1; //可以根据具体的情况来修改这个值
linklist->head.next=NULL;
3.插入元素
cpp
/*
步骤:
1.在指定位置上插入元素,先判断pose的合法性,遍历中发现达不到pos位置,返回NULL
2.在pos位置上插入,就要找到pos-1的位置
3. pos=1 逻辑的位置上插入,就定义cnt=0就是头节点
4. pos的取值范围是[1......
*/
//不推荐这个方法,实际工作中链表的插入,推荐头插法,而不是任意位置插入
int insertLinkList(LinkList *linklist,int pos,Element e){
int cnt=0;
ListNode *node=&linklist->head; //node是辅助指针
if(pos<1||pos>linklist->len+1){ //判断pos范围
printf("insert pos invalid!\n");
return -1; //结束程序
}
// 找到pos-1的位置
while(node&&cnt<-1){
node=node->next;
++cnt;
}
//node==null和pos的位置正好找到
if(node==NULL){
printf("insert pos bigger than link len!\n");
return -1;
}
//这里的node指向待插入节点的前一个节点
LinkNode *newNode=(ListNode *)malloc(sizeof(ListNode));
if(newNode==NULL){
return -1;
}
newNode->value=0;
newNode->next=node->next;
node->next=newNode;
++linkList->len;
return 0;
}
4.显示链表
cpp
void showLinkList(LinkList *linklist){
ListNode *node=linkList->head.next;
while(node){
//每个节点要做的事情
printf("%d\t",node->value);
node=node->next;
}
printf("\n");
}
//带头节点的单向链表测试案例
void test01(){
LinkList *linklist=createLinkList();
if(linklist==NULL){
return -1;
}
for(int i=0;i<5;++i){
//头插法 倒序
insertLinkList(linklist,1,i+100);
}
showLinkList(linklist);
releaseLinkList(linklist);
}
int main(){
test01();
return 0;
}
二、链表倒序的方法
- 每个节点,进行头插法的遍历
- 栈
三、删除
cpp
int deleteLinkList(LinkList *linklist,Element e){
//1.找到e的前一个节点
ListNode *node=&linklist->head;
while(node->next && (node->next->value!=e)){
node=node->next;
}
if(node->next==NULL){
printf("Not find element!\n");
return -1;
}
//2.采用备份思想,实现链式删除
ListNode *tmp=node->next;
node->next=tmp->next;
free(tmp);
--linklist->len;
四、释放
cpp
void releaseLinkList(LinkList *linklist){
if(linklist){
ListNode *node=&linklist->head;
while(node->next){
ListNode *tmp=node->next;
node->next=tmp->next;
free(tmp);
--LinkList;
}
printf("LinkList have %d node!\n",linklist->len);
free(linklist); //释放头节点
}
}
五、面试题(链表倒序)
1.先画图

2.代码部分
cpp
//第一种方法
void reverseLinkList(LinkList *linkList){
ListNode *node=linklist->head.next; //大哥
Listnode *tmp; // 小弟
linklist->head.next=NULL;
while(node){
tmp=node;
node=node->next;
tmp->next=linklist->head.next;
linklist->head.next=tmp;
}
//第二种方法
while(node){
tmp=node->next;
node->next=linklist->head.next;
linklist->head.next=node;
node=tmp;
}
六、循环链表
1.遍历
cpp
while(node!=&head){
node=node->next;
}
2.单向循环链表:频繁进行头插和尾插
双向循环链表:需要倒数第几个元素时用