头插法和尾插法

链表的头插法和尾插法

表结构的声明

typedef int ElemType;
typedef struct node //定义链表的结点的结构
{
	ElemType data;//定义链表的数据域
	struct node *next;//定义链表中的指针域
}slink;

头插法

1,从一个空表开始,重复读入数据,生成新结点。
2,将读入数据存放到新结点的数据域中。
3,将新结点插入到当前链表的表头上。
4,直到读入n个元素为止。截取自教材
现在配上代码

void Headinsert(slink *s,int n) //创造一个头插法的表,结构类型是slink;"n"是这个链表的长度
{
	slink *p;//再定义一个p(其结构与*s一样)
	int i;
	if (n < 1)
	{
		printf("链表的长度有误,请重新输入");
		return;
	}

	s = NULL;//在这里,我把s作为头指针 相当于head =NULL(目的是让头指针为空)
/*---------------------以下内容为核心,务必认真理解!!!----------------   */
	for (i = 1; i <= n; i++)//开始创建单链表
	{
		p = (slink*)malloc(sizeof(slink));
		printf("请输入第%d的数值\n",i);
		scanf_s("%d",&p->data);//输入的值存入到data里面;
		//把头指针里的内容给p的next
		s = p;//再让头指针s 指向p->data(因为在下一次循环中就会把s中的内容,赋值到p—>next) 
	}

我现在输入一下这几个数来演示下:

p->next = s;//把头指针里的内容给p的next

在这里插入图片描述
在这里插入图片描述

可以看到先输入的数25,在输出的时候变到了最后一个,我们可以这样考虑,头插法相当于你在食堂排队打饭,这时候来个人,突然插队,它插的位置还是第一个。在这里插入图片描述

尾插法

在这里插入图片描述

void Tailinsert(slink *s,int n) //创建尾插法
{
	slink *r, *p;
	if (n < 1) 
	{
		printf("链表的长度有误,请重新输入");
		return;
	}
	r = s = (slink*)malloc(sizeof(slink));//创建头结点(注:头插法没有)
	for (int i = 1; i <= n; i++)
	{
		p = (slink*)malloc(sizeof(slink));
		printf("请输入第%d的数值\n",i);
		scanf_s("%d",&p->data);
		r->next = p;//把新声明的值p给 r->next(在这里我们定义的“r”是头结点,因为头结点不能移动所以用的是头结点的另一变量r)
		r = p;//使指针r指向p
	}
	r->next = NULL;//在结束循环后使最后一个结点为NULL;
	
}

在这里插入图片描述
尾插法相对简单,理解了头插法,尾插法就很简单了,我现在输入与头插法相同的数据。
在这里插入图片描述
可以发现,我们怎么输入的,它就怎么显示,按到我们的顺序来的

总体代码

#include<stdio.h>
#include<stdlib.h>

typedef int ElemType;
typedef struct node //定义链表的结点的结构
{
	ElemType data;//定义链表的数据域
	struct node *next;//定义链表中的指针域
}slink;

void Headinsert(slink *s,int n) //创造一个头插法的表,结构类型是slink;"n"是这个链表的长度
{
	slink *p;//再定义一个p(其结构与*s一样)
	int i;
	if (n < 1)
	{
		printf("链表的长度有误,请重新输入");
		return;
	}

	s = NULL;//在这里,我把s作为头指针 相当于head =NULL(目的是让头指针为空)

	for (i = 1; i <= n; i++)//开始创建单链表
	{
		p = (slink*)malloc(sizeof(slink));
		printf("请输入第%d的数值\n",i);
		scanf_s("%d",&p->data);//输入的值存入到data里面;
		p->next = s;//把头指针里的内容给p的next
		s = p;//再让头指针s 指向p->data(因为在下一次循环中就会把s中的内容,赋值到p—>next) 
	}
	printf("该链表内的数据为:\n");
	for (int j = 0; j < n; j++)
	{
		printf("  %d  ", s->data);//显示当前数据
		s = s->next;
	}
	printf("\n");
}
void Tailinsert(slink *s,int n) //创建尾插法
{
	slink *r, *p;
	if (n < 1) 
	{
		printf("链表的长度有误,请重新输入");
		return;
	}
	r = s = (slink*)malloc(sizeof(slink));//创建头结点(注:头插法没有)
	for (int i = 1; i <= n; i++)
	{
		p = (slink*)malloc(sizeof(slink));
		printf("请输入第%d的数值\n",i);
		scanf_s("%d",&p->data);
		r->next = p;//把新声明的值p给 r->next(在这里我们定义的“r”是头结点,因为头结点不能移动所以用的是头结点的另一变量r)
		r = p;//使指针r指向p
	}
	r->next = NULL;//在结束循环后使最后一个结点为NULL;
	for (int j = 0; j < n; j++)
	{
		printf("  %d  ", s->next->data);//在这里我为啥用s->next->data 原因是直接用s->data 的话出现的数据是头结点,头结点没有数值,所以无法显示
		s = s->next;//定位到下个结点
	}
	printf("\n");
}
void selecttion(int button,int n) 
{
	slink s;
	if (button == 1)
	{
		printf("你选择的是头插法\n");
		Headinsert(&s, n);
	}
	else if (button == 2)
	{
		printf("你选择的是尾插法\n");
		Tailinsert(&s, n);
	}
	else
	{
		printf("输入错误指令,请重新输入\n");
		scanf_s("%d",&button);
		selecttion(button,n);
	}
}
int main() 
{
	int n,button;
	char Exit;
	printf("请输入链表的长度n\n");
	scanf_s("%d", &n);
	printf("以哪种方式生成链表?1.头插法 2.尾插法\n");
	scanf_s("%d", &button);
	selecttion(button, n);
	printf("是否退出?y/n\n");
	getchar();
	scanf_s("%c", &Exit);
	if (Exit == 'y')
	{
		exit(0);
	}
	return main();
}

总结

1,了解了尾插法与头插法的区别
2,在写main函数时,发现有些代码,只能在指定的结构完成。
3,我在写代码时,并没有声明head,我用的*s 就拿来代替了head
4,尾插法遍历的时候一定要写成s->next->data 因为他第一个是,空节点,如果运行的话会出现错误,所以要next
--------------------------------------------------------------------------------2020.03.16


版权声明:本文为qq_36754161原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。