目录
1.有关数据结构的体系
2.带头节点的单项不循环链表
利用链表实现函数功能
1)创建.h文件进行宏定义
#ifndef LIST_H__
#define LIST_H__
typedef struct node_st
{
int data;
struct node_st *next;
}LIST;
LIST *list_create();
void list_create1(LIST **p);
int list_isempty(LIST *);
//pos
int list_insert(LIST *,int pos, int *newdata);
int list_delete(LIST *,int pos, int *newdata);
//value
int list_insert_value(LIST *,int *newdata);
int list_delete_value(LIST *,int *newdata);
int list_find(LIST *,int *data);
void list_display(LIST *);
void list_destroy(LIST *);
#endif
2)为链表动态分配空间
①通过返回的方式
LIST *list_create()
{
LIST *p;//定义一个结构体类型的指针
p = malloc(sizeof(*p)); //分配动态空间
if(p == NULL) //判断是否为空
return NULL;
p->next = NULL;
return p;
}
②透过设置参数的方式
void list_create1(LIST **p)
{
*p = malloc(sizeof(**p)); //动态分配空间
if(*p == NULL) //判断是否分配成功
return ;
(*p)->next = NULL;
return ;
}
3)判断链表是否为空
int list_isempty(LIST *p)
{
if(p->next == NULL)
return 1;
return 0;
}
4)插入数据
int list_insert(LIST *ptr,int pos, int *newdata)
{
int i = 0;
LIST *p = ptr,*q;
while(i < pos && p ) //链表遍历,找到pos位置,并且指针不为空
{
p = p->next;
i++;
}
if(p)
{
q = malloc(sizeof(*q)); //给新定义的结构体指针变量分配空间
if(q == NULL)
return -1;
q->data = *newdata; //将要插入的值 赋值给变量q的data
q->next = p->next; //将p中next指向的地址 赋值给q的next
p->next = q; //将q的地址给p的next
return 0;
}
else
return -2;
}
插入数据时,需要先动态分配一个空间(q)来保存插入的数据,将插入位置前驱结点(p)中的next赋值给q中的next,前驱结点(q)中的next保存q的地址
5)删除数据
int list_delete(LIST *ptr,int pos, int *newdata)
{
int i = 0;
LIST *p = ptr,*q;
if(list_isempty(ptr)) //判断链表是否为空
return -2;
while(i < pos && p ) //遍历,找到所要删除的位置前驱结点
{
p = p->next;
i++;
}
if(p)
{
q = p->next; //所要删除的位置
p->next = q->next; //将删除位置的next赋值给前驱结点,赋值完成后它的前驱结点指向它的后继结点
if(newdata != NULL)
*newdata = q->data;
free(q); 将所要删除的结点释放
q = NULL;
return 0;
}
else
return -1;
}
删除结点时要先找到它的前驱结点,再让它的前驱结点指向它的后继结点,之后将所要删除位置空间释放
6)查找数据,并返回数据所对应的下标
int list_find(LIST *ptr,int *data)
{
int i=0;
if(list_isempty(ptr))
return 0;
LIST *p = ptr->next;
while(p->data!=*data)
{
i++;
p = p -> next;
if(p==NULL)
{
return 0;
}
}
return i;
}
7)按顺序插入数据
int list_insert_value(LIST *ptr,int *newdata)
{
LIST *p = ptr,*q;
while(p->next && p->next->data < *newdata) //当p不为NULL并且当插入的数据大于链表中的数据时,p指针向后移
p = p->next;
q = malloc(sizeof(*q)); //给q动态分配一个空间
if(q == NULL)
return -1;
q->data = *newdata;
q->next = p->next; //将p中的next赋值给q的next
p->next = q; //将q的地址赋值给p的next
return 0;
}
8)按值删除
int list_delete_value(LIST *ptr,int *newdata)
{// -> - 2 4 6 8 *newdata = 6;
LIST *p = ptr,*q;
if(list_isempty(ptr))
return -2;
while(p->next && p->next->data != *newdata) //当不p->next不为空并且数据不相等,向后移
p = p->next;
if(p->next == NULL)
return -1;
else
{
q = p->next; //将p的next赋值给q
p->next = q->next; //将q中的next赋值给p的next
free(q); //释放q的空间
q = NULL;
return 0;
}
}
9)输出链表中的值
void list_display(LIST *ptr)
{
LIST *p = ptr->next;
if(list_isempty(p))
return ;
while(p)
{
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
10)释放空间
void list_destroy(LIST *ptr)
{
LIST *p = ptr->next,*q;
if(list_isempty(p))
return ;
while(p)
{
q = p->next;
free(p);
p = q;
}
free(ptr);
}
3.一元多项式的合并
1)定义结构体
typedef struct num_st
{
int coef;
int exp;
struct num_st *next;
}NUM;
2) 创建链表
NUM *poly_create(int (*a)[2],int n)
{
int i;
NUM *p,*head,*q;
head=malloc(sizeof(*head)); //动态分配空间
if(head==NULL)
{
return NULL;
}
head->next = NULL;
p=head;
for(i=0;i<n;i++)
{
q = malloc(sizeof(*q));
if(q == NULL)
return NULL;
q->coef = a[i][0]; //将数组中第一列中的数赋值到链表中(方程式中的常数)
q->exp = a[i][1]; //将数组中第二列中的数赋值到链表中(幂次)
q->next = NULL;
p->next= q; //将q地址保存到p的next中
p=q; //将q赋值给p 意思是p向后移
}
return head;
}
3)输出链表
void display(NUM *head)
{
NUM *p=head->next;
while(p)
{
printf("(%d,%d)",p->coef,p->exp);
p=p->next;
}
printf("\n");
}
4)合并链表
void poly_add(NUM *ptr1,NUM *ptr2)
{
NUM *r = ptr1;
NUM *p = ptr1->next;
NUM *q = ptr2->next;
while(p && q) //判断当p和q都不为NULL时,执行循环
{
if(p->exp < q->exp) //判断 当p的exp(幂)值小于q的exp(幂)值
{
r->next=p; //将p赋值给r的next
r=p; //r向后移
p=p->next; //p向后移
}
else //判断 当p的exp(幂)值大于或等于q的exp(幂)值
{
if(p->exp>q->exp)
{
r->next = q; //将q赋值给r的next
r = q; //r向后移
q=q->next; //q向后移
}
else
{
p->coef += q->coef;//当幂相等时,两个系数相加,保存到p的coef中
if(p->coef) //判断系数是否为0
{
r->next=p; //p赋值到r的next中
r=p; //r向后移
}
p=p->next; //p后移
q=q->next; //q后移
}
}
}
if(p==NULL) //当p链表为空时,连接q
r->next=q;
else //当q链表为空时,连接p
r->next=p;
}
4.不带头节点的单项循环链表
约瑟夫环
1)定义结构体
typedef struct node_st
{
int data;
struct node_st *next;
}JOSEPHU;
2)创建循环链表
JOSEPHU *josephu_create(int n)
{
JOSEPHU *l,*p,*q;
int i = 1;
l = malloc(sizeof(*l));
if(l == NULL)
return NULL;
l->data = i; //给第一个结点赋值
l->next = l; //让第一个结点指向第一个结点
p = l;
i++;
while(i <= n)
{
q = malloc(sizeof(*q));
if(q == NULL)
return NULL;
q->data = i; //给结点赋值
i++;
q->next = l; //让最后一个结点指向第一个
p->next = q; //将p的next指向q 用于链表连接
p = q; //q赋值给p
}
return l;
}
3)显示链表
void josephu_show(JOSEPHU *l)
{
JOSEPHU *p = l;
while(p->next != l)
{
printf("%d ",p->data);
p = p->next;
}
printf("%d\n",p->data);
}
4)删除直到最后一个
void josephu_kill(JOSEPHU **l, int n)
{
int i = 1;
JOSEPHU *p = *l,*q;
printf("KILL:");
while(p->next != p) //当指向自己的时候循环结束
{
while(i < n) //寻找第n个
{
q = p;
p = p->next;
i++;
}
q->next = p->next;
printf("%d ",p->data);
free(p);
i = 1;
p = q->next;
}
printf("\n");
*l = p;
}
注:本文是通过听李慧芹老师上课记的笔记,如有理解不到位请多多包涵,也请多多指教