一. 单链表
1.1 单链表查找中心节点
快慢指针法
cpp
//查找返回链表的中间节点
//快慢指针
Node_t *find_mid_node(Link_t *plink)
{
if(plink->phead == NULL)
return NULL;
Node_t *slow = plink->phead, *fast = plink->phead;
while(fast && fast->pnext)
{
slow = slow->pnext;
fast = fast->pnext->pnext;
}
return slow;
}
1.2 单链表查找并且修改
cpp
//链表查找
Node_t *find_link(Link_t *plink, DATATYPE_T target)
{
if(plink->phead == NULL)
return NULL;
Node_t *cur = plink->phead;
while(cur)
{
if(cur->data == target)
return cur;
cur = cur->pnext;
}
return NULL;
}
//修改链表指定节点
int modify_link(Link_t *plink, DATATYPE_T olddata ,DATATYPE_T newdata)
{
Node_t *ptarget = find_link(plink, olddata);
if(ptarget == NULL)
return -1;
else
ptarget->data = newdata;
return 0;
}
1.3 单链表查找倒数第k个节点
cpp
//查找链表倒数第k个节点
Node_t *find_last_k_node(Link_t *plink, int k)
{
assert(plink);
if(is_empty_link(plink) || k <= 0)
{
return NULL;
}
Node_t *pfast = plink->phead;
Node_t *pslow = pfast;
while(k--)
{
if(pfast == NULL)
{
return NULL;
}
pfast = pfast->pnext;
}
while(pfast)
{
pfast = pfast->pnext;
pslow = pslow->pnext;
}
return pslow;
}
1.4 单链表反转
方法一:头插法
cpp
//反转链表1
//头插法
int reverse_link1(Link_t *plink)
{
assert(plink);
if(is_empty_link(plink))
{
return -1;
}
Node_t *pinsert = plink->phead;
Node_t *ptemp = pinsert;
plink->phead = NULL;
while(pinsert)
{
ptemp = ptemp->pnext;
pinsert->pnext=plink->phead;
plink->phead = pinsert;
pinsert = ptemp;
}
return 0;
}
方法二:三指针法
cpp
//反转链表2
//三指针法
int reverse_link2(Link_t *plink)
{
assert(plink);
if(is_empty_link(plink))
{
return -1;
}
Node_t *prev = NULL, *cur = plink->phead;
Node_t *next = NULL;
while(cur)
{
next = cur->pnext;
cur->pnext = prev;
prev = cur;
cur = next;
}
plink->phead = prev;
return 0;
}
方法三:迭代法
cpp
//反转链表3
//递归
Node_t *reverse_link3(Node_t *phead)
{
if(phead == NULL || phead->pnext ==NULL)
return phead;
else
{
Node_t *newhead = reverse_link3(phead->pnext);
phead->pnext->pnext = phead;
phead->pnext = NULL;
return newhead;
}
}
1.5 单链表的插入排序
cpp
void sort_link_insert(Link_t *plink)
{
//空链表或者只有一个节点则返回
if(is_empty_link(plink) || plink->phead->pnext == NULL)
return;
Node_t *pinsert = NULL;
Node_t *ptemp = plink->phead->pnext;
plink->phead->pnext = NULL;//断开第一个节点
while(ptemp)
{
pinsert = ptemp;
ptemp = ptemp->pnext;
if(pinsert->data <= plink->phead->data)//如果比头节点小则头插,并且成为新的头
{
pinsert->pnext = plink->phead;
plink->phead = pinsert;
}
else
{
Node_t *p = plink->phead;
while(p->pnext && pinsert->data > p->pnext->data)//找到要插入的位置
{
p = p->pnext;
}
pinsert->pnext = p->pnext;
p->pnext = pinsert;
}
}
}
数组的插入排序:
cpp
void insert_sort(int *arr, int size)
{
int i = 0, j = 0;
for(i = 1; i < size; i++){
j = i;
int temp = arr[j];
while(j > 0 && arr[j - 1] > temp){
arr[j] = arr[j - 1];
j--;
}
arr[j] = temp;
}
}
1.6 单链表判断有环
cpp
//判断有环链表
//快慢指针法
int is_loop_link(Link_t *plink)
{
if(is_empty_link(plink) || plink->phead->pnext == NULL)
return 0;
Node_t *fast = plink->phead;
Node_t *slow = fast;
while(fast && fast->pnext)
{
fast = fast->pnext->pnext;
slow = slow->pnext;
if(fast == slow)
return 1;
}
return 0;
}
二. 双链表
2.1 双链表结构

2.2 双链表的实现
2.2.1 声明
cpp
//类型重命名
typedef struct stu{
int id;
int score;
char name[20];
}DataType_t;
//双链表节点结构体
typedef struct doulinknode{
DataType_t data;
struct doulinknode *pnext;
struct doulinknode *ppre;
}DNode_t;
//双链表对象结构体
typedef struct doulink{
DNode_t *phead;
int len;
}DLink_t;
2.2.2 双链表对象的创建
cpp
//创建双链表对象
DLink_t *creat_dlink()
{
DLink_t *pdlink = malloc(sizeof(DLink_t));
if(pdlink == NULL){
printf("malloc error\n");
return NULL;
}
pdlink->phead = NULL;
pdlink->len = 0;
return pdlink;
}
2.2.3 双链表节点的创建与判空
cpp
//创建双链表新节点
DNode_t *creat_dnode(DataType_t data)
{
DNode_t *pdnode = malloc(sizeof(DNode_t));
if(pdnode == NULL){
printf("malloc error\n");
return NULL;
}
pdnode->data = data;
pdnode->pnext = NULL;
pdnode->ppre = NULL;
return pdnode;
}
//判空
bool is_empty_dlink(DLink_t *pdlink)
{
return pdlink->len == 0;
}
2.2.4 双链表头插
cpp
//链表头插
int insert_dlink_head(DLink_t *pdlink, DataType_t data)
{
DNode_t *pnewpnode = creat_dnode(data);
if(pnewpnode == NULL){
printf("creat_dnode error\n");
return 0;
}
if(is_empty_dlink(pdlink)){
pdlink->phead = pnewpnode;
}
else{
pnewpnode->pnext = pdlink->phead;
pdlink->phead->ppre = pnewpnode;
pdlink->phead = pnewpnode;
}
pdlink->len++;
return 1;
}
2.2.5 双链表头删
cpp
//双链表头删
int delete_dlink_head(DLink_t *pdlink)
{
if(is_empty_dlink(pdlink)){
return 0;
}
DNode_t *pfree = pdlink->phead;
//只有一个节点的情况
if(pdlink->len == 1){
free(pfree);
pfree = NULL;
pdlink->phead = NULL;
}
else{
pfree->pnext->ppre = NULL;
pdlink->phead = pfree->pnext;
free(pfree);
pfree = NULL;
}
pdlink->len--;
2.2.6 双链表尾插
cpp
//双链表尾插
int insert_dlink_tail(DLink_t *pdlink, DataType_t data)
{
//空链表,头插即可
if(is_empty_dlink(pdlink)){
insert_dlink_head(pdlink, data);
return 1;
}
DNode_t *pnewnode = creat_dnode(data);
DNode_t *ptail = pdlink->phead;
while(ptail->pnext){
ptail = ptail->pnext;
}
ptail->pnext = pnewnode;
pnewnode->ppre = ptail;
pdlink->len++;
return 1;
}
2.2.7 双链表尾删
cpp
//双链表尾删
int delete_dlink_tail(DLink_t *pdlink)
{
if(is_empty_dlink(pdlink)){
return 0;
}
//只有一个节点情况
if(pdlink->phead->pnext == NULL){
delete_dlink_head(pdlink);
}
else{
DNode_t *tail = pdlink->phead;
while(tail->pnext){
tail = tail ->pnext;
}
tail->ppre->pnext = NULL;
free(tail);
tail = NULL;
pdlink->len--;
return 1;
}
}
2.2.8 双链表销毁
cpp
//销毁双链表
void destroy_dlink(DLink_t *pdlink)
{
while(!is_empty_dlink(pdlink)){
delete_dlink_head(pdlink);
}
free(pdlink);
pdlink = NULL;
}
2.2.9 双链表查找
cpp
//双链表查找
DNode_t *find_dlink(DLink_t *pdlink, int id)
{
if(is_empty_dlink(pdlink)){
return NULL;
}
DNode_t *ptarget = pdlink->phead;
while(ptarget){
if(ptarget->data.id == id){
break;
}
ptarget = ptarget->pnext;
}
return ptarget;
}
2.2.10 双链表修改
cpp
//双链表修改
//成绩
void modify_dlink(DLink_t *pdlink, int id, int score)
{
DNode_t *ptarget = find_dlink(pdlink, id);
if(ptarget == NULL){
printf("找不到");
return;
}
ptarget->data.score = score;
printf("修改成功\n");
}
//名字
void modify_dlink(DLink_t *pdlink, int id, char *str)
{
DNode_t *ptarget = find_dlink(pdlink, id);
if(ptarget == NULL){
printf("找不到");
return;
}
strcpy(ptarget->data.name,str);
printf("修改成功\n");
}
2.2.11 双链表插入排序
cpp
//双链表插入排序
void sort_dlink_insert(DLink_t *pdlink)
{
if(is_empty_dlink(pdlink) || pdlink->len == 1){
return;
}
DNode_t *ptemp = pdlink->phead->pnext;
DNode_t *pinsert = NULL;
//断开链表
pdlink->phead->pnext = NULL;
ptemp->ppre = NULL;
while(ptemp){
pinsert = ptemp;
ptemp = ptemp->pnext;
// ptemp->ppre = NULL;//注意不能有这句,当上一步使ptemp为NULL时,这一步会段错误
if(pinsert->data.score <= pdlink->phead->data.score){
pinsert->pnext = pdlink->phead;
pdlink->phead->ppre = pinsert;
pinsert->ppre = NULL;
pdlink->phead = pinsert;
}
else{
DNode_t *p = pdlink->phead;
while(p->pnext && p->pnext->data.score < pinsert->data.score){
p = p->pnext;
}
pinsert->pnext = p->pnext;
//这个判断也一定要有,不然当p指向尾节点时, p->pnext->ppre这样访问NULL会报段错误
if(p->pnext){
p->pnext->ppre = pinsert;
}
p->pnext = pinsert;
pinsert->ppre = p;
}
}
}