带头结点的单链表
1.实验目的
1、理解带头结点的单链表的特点,掌握采用这种结构的算法设计
2、熟练掌握运用带头结点链表表示特定形式的数据的方法,并设计出有关算法
2.实验内容
1、用尾插法建立带头节点的单链表
2、用头插法建立带头节点的单链表
3、打印输出
4、删除列表中所有奇数
5、有序表插入
6、两降序表合并成升序表
3.设计思路
先通过尾插法或者头插法建立带头结点的单链表,造结点,赋值,插入,修改表尾。再进行系列操作如打印输出、删除奇数、有序表的插入,两降序表合并成升序表。
4.实验代码
#include <stdio.h>
#include <stdlib.h>
#define newNode (LinkedList *)malloc(sizeof(LinkedList))
typedef struct k
{
int data;
struct k *next;
} LinkedList;
/**********************************************/
//1.建表:尾插法
//函数功能:用尾插法建立带头节点的单链表
//函数参数:空
//函数返回值:指向LinkedList类型变量的指针head
//函数名:TailInsert()
/**********************************************/
LinkedList *TailInsert()
{
int x;
LinkedList *head, *p, *tail;
head=(LinkedList *)malloc(sizeof(LinkedList)); //创建头节点,为头节点开辟内存空间
head->next=NULL; //对next初始化
//向链表中添加元素
printf("input the node number(end with -1):");
scanf("%d",&x);
tail=head;
while(x!=-1)
{
//1.创建新节点
p=newNode; //p=(LinkedList *)malloc(sizeof(LinkedList))
//2.对p的各个域赋初值
p->data=x;
p->next=NULL;
//3.将p插入链表尾部,并将tail修改成新的表尾
tail->next=p;
tail=p;
//4.继续读一个值x
scanf("%d",&x);
}
if(tail!=NULL)
tail->next=NULL;
return head;
}
/**********************************************/
//1.建表:头插法
//函数功能:用头插法建立带头节点的单链表
//函数参数:空
//函数返回值:指向LinkedList类型变量的指针head
//函数名:HeadInsert()
/**********************************************/
LinkedList *HeadInsert()
{
int x;
LinkedList *head, *p;
head=(LinkedList *)malloc(sizeof(LinkedList)); //创建头节点,为头节点开辟内存空间
head->next=NULL; //对next初始化
//向链表中添加元素
printf("input the node number(end with -1):");
scanf("%d",&x);
while(x!=-1)
{
//1.创建新节点
p=newNode;
//2.对q的各个域赋初值
p->data=x;
p->next=NULL;
//3.将p插入head之后
p->next=head->next;
head->next=p;
//4.继续读一个值x
scanf("%d",&x);
}
return head;
}
/***************************************/
//2.打印输出
//函数功能:打印带头节点的单链表head
//函数参数:指向LinkedList类型变量的指针head
//函数返回值:
//函数名:
/***************************************/
void show(LinkedList *head) //打印带头节点的单链表head
{
LinkedList *p;
for(p=head->next; p!=NULL; p=p->next)
printf("%d ",p->data);
}
/*********************************************************************/
//3.删除列表中所有奇数
//函数功能:删除列表中所有奇数
//函数参数:指向LinkedList类型变量的指针head
//函数返回值:空
//函数名:delete_special()
/*********************************************************************/
void delete_special(LinkedList *head)
{
LinkedList *p,*pre, *q;
if(head->next==NULL)
return; //空表,直接返回
pre=head;
p=head->next;
while(p!=NULL)
{
if(p->data%2==1)
{
//1.将q贴在p上
q=p;
//2.将p与pre向后移
p=p->next;
pre->next=p;
//3.释放q的内存空间
free(q);
}
else
{
p=p->next;
pre=pre->next;
}
}
}
/************************************************************************/
//5.有序表插入
//函数功能:将x插入升序表(降序表应该就是把for循环里的条件改一下吧,就没写)
//函数参数:指向LinkedList类型变量的指针head int类型变量x
//函数返回值:空
//函数名:insert_organizedList()
/************************************************************************/
void insert_organizedList(LinkedList *head, int x)
{
LinkedList *p,*pre,*q;
//可以不进行单独判断
/*
if(head->next==NULL)
{
printf("该单链表为空表!无法进行操作!");
return; //空表,直接返回
}
//非空表,进行寻找插入x位置的操作
*/
//printf("请输入要插入的值x:");
//scanf("%d",&x);
for(pre=head,p=head->next; p!=NULL && x>p->data; p=p->next,pre=pre->next);
//1. 为新的节点开辟内存空间
q=newNode;
//2.为q的各个域赋值
q->data=x;
q->next=NULL;
//3.插入节点q在p与pre之间
q->next=p;
pre->next=q;
printf("head=");
show(head);
}
/************************************************************/
//6.两降序序表合并成升序表
//函数功能:两降序序表合并成升序表
//函数参数:指向LinkedList类型变量的指针head1, head2, head 3
//函数返回值:空
//函数名:merge_List
/************************************************************/
void merge_List(LinkedList *head1, LinkedList *head2, LinkedList *head3)
{
LinkedList *p,*q,*r;
head3->next==NULL; //新创建的表必须是空表
p=head1->next;
q=head2->next;
while(p!=NULL && q!=NULL)
{
if(p->data>q->data)
{
r=p; //把r贴在q上面,选中r
p=p->next; // 把p向后移动
//用头插法创建head3
r->next=head3->next;
head3->next=r;
}
else
{
r=q; //把r贴在p上面,选中r
q=q->next; // 把p向后移动
//用头插法创建head3
r->next=head3->next;
head3->next=r;
}
}
//一定会有一个表先扫描至表尾,对剩下的元素进行处理
while(p!=NULL)
{
r=p; //把r贴在q上面,选中r
p=p->next; // 把p向后移动
//用头插法创建head3
r->next=head3->next;
head3->next=r;
}
while(q!=NULL)
{
r=q; //把r贴在p上面,选中r
q=q->next; // 把p向后移动
//用头插法创建head3
r->next=head3->next;
head3->next=r;
}
}
int main()
{
LinkedList *head;
//1.建表:尾插法
head=TailInsert();
//1.建表:头插法
head=HeadInsert();
//2.打印输出
printf("head=");
show(head);
//3.删除列表中所有奇数
delete_special(head);
printf("head=");
show(head);
//4.有序表插入
printf("\n");
int x;
insert_organizedList(head,1);
//5.两降序序表合并成升序表
LinkedList *head1, *head2, *head3;
//用尾插法创建head1
head1=TailInsert();
printf("head1=");
show(head1);
printf("\n");
//用尾插法创建head2
head2=TailInsert();
printf("head2=");
show(head2);
printf("\n");
head3=newNode; head3->next=NULL;
merge_List(head1, head2, head3);
printf("head3=");
show(head3);
}
5.运行结果
![](https://i-blog.csdnimg.cn/blog_migrate/615b96fdbb599f90cc08a9ee600c4072.jpeg)
6.实验总结(含心得体会)
通过这次实验,我学习到了用尾插法建立带头节点的单链表、用头插法建立带头节点的单链表、打印输出、删除列表中所有奇数、有序表插入、两降序表合并成升序表等算法操作,本次实验和上一次不带头结点的实验有异曲同工之处,我们要从中寻找出相似点,这样的话实验效率可以得到提高。