一.单向链表(带头节点)的任意位置插入,代码实现
- 定义链表的节点和表头
//定义节点(链表的核心)
typedef int Element;
typedef struct list_node{Element value;struct list_node *next;
}ListNode;//链表的表头
typedef struct{ListNode head;int len;
}LinkList;
2.创建链表及初始化
#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.插入元素
/*
步骤:
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.显示链表
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;
}
二、链表倒序的方法
- 每个节点,进行头插法的遍历
- 栈
三、删除
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;
四、释放
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.代码部分
//第一种方法
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.遍历
while(node!=&head){node=node->next;}
2.单向循环链表:频繁进行头插和尾插
双向循环链表:需要倒数第几个元素时用