一:单向链表(头插、删,尾插、删,遍历,按位置插入、删除,直接插入排序,链表翻转,快慢指针,释放链表)
1.main函数
#include <stdio.h>
#include "./03_linklistFunc.h"
int main(int argc, const char *argv[])
{
Linklist* head;
head = create_linklist();
insert_linklistByHead(head, 100); //100
insert_linklistByHead(head, 200); //200 100
insert_linklistByHead(head, 300); //300 200 100
show_linklist(head);
insert_linklistByWei(head, 666); //300 200 100 666
insert_linklistByWei(head, 999); //300 200 100 666 999
show_linklist(head);
delete_linklistByHead(head);
show_linklist(head); //200 100 666 999
delete_linklistByHead(head);
show_linklist(head); //100 666 999
delete_linklistByHead(head);
show_linklist(head); //666 999
insert_linklistSort(head,777); //666 777 999
show_linklist(head);
insert_linklistSort(head,555); //555 666 777 999
show_linklist(head);
insert_linklistSort(head,1111); //555 666 777 999 1111
show_linklist(head);
printf("middle num=%d\n", middleNode_linklist(head));//middle num=777
datatype num=delete_linklistByWei(head);
show_linklist(head); //555 666 777 999
printf("num=%d\n", num); //num=1111
insert_linklistWeiZhi(head, 444, 1);
show_linklist(head); //444 555 666 777 999
insert_linklistWeiZhi(head, 888, 5);
show_linklist(head); //444 555 666 777 888 999
insert_linklistWeiZhi(head, 1111, 7);
show_linklist(head); //444 555 666 777 888 999 1111
insert_linklistWeiZhi(head, 2222, 9); //n=9插入位置不合法,按位置插入失败
insert_linklistWeiZhi(head, 222, 0); //n=0插入位置不合法,按位置插入失败
delete_linklistByWeiZhi(head, 0); //=0要删除的位置不合法
delete_linklistByWeiZhi(head, 1);
show_linklist(head); //555 666 777 888 999 1111
delete_linklistByWeiZhi(head, 7); //n=7要删除的位置不合法
delete_linklistByWeiZhi(head, 6);
show_linklist(head); //555 666 777 888 999
fanzhuan_linklist(head);
show_linklist(head); //999 888 777 666 555
free_linklist(&head);
return 0;
}
2.头文件
#ifndef __LINKLIST__
#define __LINKLIST__
typedef int datatype;
typedef struct lklst
{
union
{
int len; //若是头结点,则用len存储链表长度
datatype data; //若是有效数据结点,则用data存放有效数据
}text; //数据域
struct lklst* next;//指针域,指向下一个结点,存储下一个结点的首地址
}Linklist;
//创建一个空的单链表
Linklist* create_linklist(void);
//头插法插入数据
void insert_linklistByHead(Linklist* head, datatype num);
//尾插法插入数据
void insert_linklistByWei(Linklist* head, datatype num);
//头删法删除数据
datatype delete_linklistByHead(Linklist* head);
//尾删法删除数据
datatype delete_linklistByWei(Linklist* head);
//遍历链表
void show_linklist(Linklist* head);
//按位置插入
void insert_linklistWeiZhi(Linklist* head, datatype num, int n);
//按位置删除
void delete_linklistByWeiZhi(Linklist* head, int n);
//直接插入排序(升序)
void insert_linklistSort(Linklist* head, datatype num);
//链表翻转
void fanzhuan_linklist(Linklist* head);
//寻找中间结点(快慢指针)
datatype middleNode_linklist(Linklist* head);
//释放链表
void free_linklist(Linklist** phead);
#endif
3.功能函数
#include <stdio.h>
#include <stdlib.h>
#include "./03_linklistFunc.h"
//创建一个空的单链表
Linklist* create_linklist(void)
{
//在堆空间中申请了头结点的空间,头结点的首地址存储在head指针中
//head指针就是头指针
Linklist* head = (Linklist*)malloc(sizeof(Linklist));
if(NULL == head)
{
printf("创建单链表失败\n");
return NULL;
}
//初始化头结点中的len
head->text.len = 0;
head->next = NULL;
return head;
}
//头插法插入数据
void insert_linklistByHead(Linklist* head, datatype num)
{
//创建一个新的结点temp
Linklist* temp = (Linklist*)malloc(sizeof(Linklist));
if(NULL == temp)
{
printf("创建结点失败,头插失败\n");
return ;
}
temp->text.data = num; //数据域赋值
temp->next = NULL; //指针域赋值
//将temp头插法插入链表
temp->next = head->next;
head->next = temp;
//更新头结点中链表的长度
head->text.len++;
return ;
}
//尾插
void insert_linklistByWei(Linklist* head, datatype num)
{
//创建一个新的结点temp
Linklist* temp = (Linklist*)malloc(sizeof(Linklist));
if(NULL == temp)
{
printf("创建结点失败,尾插失败\n");
return ;
}
temp->text.data = num; //数据域赋值
temp->next = NULL; //指针域赋值
//找尾结点p的位置:循环判断p->next是否为NULL
Linklist* p=head;
while(NULL != p->next)
{
p=p->next;
}
//将temp尾插法插入链表
temp->next=NULL; //或者temp->next=p->next;
p->next=temp;
//更新头结点中链表的长度
head->text.len++;
return ;
}
//头删
datatype delete_linklistByHead(Linklist* head)
{
//先判断链表是否为NULL
if(NULL == head->next)
{
printf("链表为空,头删除失败\n");
}
//备份要释放的结点地址
Linklist* temp =head->next;
//修改head指针域中的地址,为要释放的结点的后一个结点的地址
head->next=temp->next; //或者head->next = head->next->next;
//保存要释放的结点数据域中存储的数据,作为验证
datatype num = temp->text.data;
//释放结点,防止temp变野指针,指向NULL
free(temp);
temp=NULL;
//更新头结点中链表的长度
head->text.len--;
return num;
}
//尾删
datatype delete_linklistByWei(Linklist* head)
{
//判断链表是否为空
if(NULL == head->next)
{
printf("链表为空,尾删失败\n");
return (datatype)-1;
}
//循环方式找倒数第2个结点p
Linklist* p=head;
while(p->next->next != NULL)
{
p = p->next;
}
//能运行到这里,代表p是倒数第2个结点
//备份要删除结点中的数据
datatype num = p->next->text.data;
//删除尾结点,即释放倒数第1个结点
//备份要释放的结点地址
Linklist* temp = p->next;
p->next = NULL;
free(temp);
//更新头结点中链表的长度
head->text.len--;
return num;
}
//遍历链表
void show_linklist(Linklist* head)
{
Linklist* p = head;
while(p->next != NULL)
{
p=p->next;
printf("%d ", p->text.data);
}
putchar(10);
return ;
}
//按位置插入
void insert_linklistWeiZhi(Linklist* head, datatype num, int n)
{
//判断插入位置是否合法
if(n<1)
{
printf("n=%d插入位置不合法,按位置插入失败\n", n);
return ;
}
//找要插入位置的前一个结点位置
//例如:插入位置为2,则需要找到第1个位置
Linklist* p=head;
for(int i=0; i<n-1; i++)
{
p = p->next;
//若在找的途中,p指向NULL,则代表插入位置非法
if(NULL == p)
{
printf("n=%d插入位置不合法,按位置插入失败\n", n);
return ;
}
}
//能运行到这个位置,则代表找到了要插入位置的前一个结点位置
//创建一个新的结点temp
Linklist* temp = (Linklist*)malloc(sizeof(Linklist));
if(NULL == temp)
{
printf("创建结点失败,尾插失败\n");
return ;
}
temp->text.data = num; //数据域赋值
temp->next = NULL; //指针域赋值
//将结点temp插入指定位置,即p结点的后一个位置
temp->next = p->next;
p->next = temp;
//更新头结点中链表的长度
head->text.len++;
return ;
}
//按位置删除
void delete_linklistByWeiZhi(Linklist* head, int n)
{
//先判断链表是否为空
if(NULL == head->next)
{
printf("链表为空,按位置删除失败\n");
return ;
}
//判断要删除位置是否合法
if(n<1)
{
printf("n=%d要删除的位置不合法\n", n);
return ;
}
//找到要删除的结点位置的前一个结点位置
//例如:要删除位置2的结点,要找到位置1的结点
//同时要判断如果p->next=NULL,则删除位置也不合法
Linklist* p=head;
for(int i=0; i<n-1; i++)
{
p = p->next;
if(NULL == p->next)
{
printf("n=%d要删除的位置不合法\n", n);
return ;
}
}
//按位置删除
Linklist* temp = p->next;
p->next=temp->next;
free(temp);
temp=NULL;
//更新头结点中链表的长度
head->text.len--;
return ;
}
//直接插入排序(升序)
void insert_linklistSort(Linklist* head, datatype num)
{
//创建一个新的结点temp
Linklist* temp = (Linklist*)malloc(sizeof(Linklist));
if(NULL == temp)
{
printf("创建结点失败,尾插失败\n");
return ;
}
temp->text.data = num; //数据域赋值
temp->next = NULL; //指针域赋值
Linklist* p=head;
//找要插入位置的前一个结点位置:
//判断条件:当前结点的下一个结点是否大于要插入的数据num
while(p->next != NULL)
{
if(num < p->next->text.data)
{
break;
}
p=p->next;
}
//插入temp数据
temp->next=p->next;
p->next=temp;
//更新头结点中链表的长度
head->text.len++;
return ;
}
//链表翻转
void fanzhuan_linklist(Linklist* head)
{
Linklist* head1 = head;
//创建一个临时链表head2
Linklist* head2 = create_linklist();
//定义一个用于备份的结点
Linklist* temp = NULL;
//循环将head1中的结点头插入head1
while(NULL != head1->next)
{
//将head1的后一个结点从head1链表中分离出来
//先备份head1的后一个结点
temp = head1->next;
//将head1的下一个结点修改成temp的下一个结点
head1->next = temp->next;
//将结点temp头插入head2中
temp->next = head2->next;
head2->next = temp;
}
//用head1替换head2
head1->next = head2->next;
//释放临时链表
free(head2);
head2 = NULL;
return ;
}
//寻找中间结点(快慢指针)
datatype middleNode_linklist(Linklist* head)
{
//若链表为空,fast和low都指向NULL
//此时fast->next会出现段错误
//先判断链表是否为空
if(NULL == head->next)
{
printf("链表为空,没有中间结点\n");
return (datatype)-1;
}
//定义low、fast指向头指针
Linklist* low;
Linklist* fast;
low = fast = head->next;
//循环找到中间结点
while(fast != NULL && fast->next != NULL)
{
low=low->next;
fast=fast->next->next;
}
//结束循环后,low指向的就是中间结点位置
//返回low指向结点中存储的顺序
return low->text.data;
}
//释放链表
void free_linklist(Linklist** phead)
{
//创建一个新的结点
Linklist* temp = NULL;
//循环头删直到链表为空:head->next=NULL
while(NULL != (*phead)->next)
{
temp = (*phead)->next;
(*phead)->next =temp->next;
free(temp);
(*phead)->text.len--;
show_linklist(*phead);
}
//释放头结点,将头指针置为NULL
free(*phead);
*phead = NULL;
return ;
}
二:单向循环链表(头插、删,尾插、删,遍历,按位置插入、删除)
1.main函数
#include <stdio.h> |
#include "./06_looplinklistFunc.h" |
|
int main(int argc, const char *argv[]) |
{ |
Looplinklist* head = create_looplinklist(); |
return 0; |
} |
|
2.头文件
#ifndef __LINKLIST__
#define __LINKLIST__
typedef int datatype;
typedef struct loopll
{
union{
int len; //若是头结点,用len存储链表长度
datatype data; //若是有效数据结点,则用data存放有效数据
}text; //数据域
struct loopll* next; //指针域,指向下一个结点,存储下一个结点的首地址
}Looplinklist;
Looplinklist* create_looplinklist(void);
#endif
3.功能文件
#include <stdio.h>
#include <stdlib.h>
#include "./06_looplinklistFunc.h"
//创建一个空的单向循环链表
Looplinklist* create_looplinklist(void)
{
Looplinklist* head = (Looplinklist*)malloc(sizeof(Looplinklist));
if(NULL == head)
{
printf("创建单向循环链表失败\n");
return NULL;
}
head->next = head; //自己指向自己
head->text.len = 0; //将长度赋值为0
return head;
}