后台组贾浩琛周报(2020.11.30-12.6)

C语言学习内容

链表的创建

一,链表的创建

头插法和尾插法

(1)头插法

在这里插入图片描述

Linklist Creat_list(Linklist head) {
	head = (Linklist)malloc(sizeof(Lnode));      //  为头指针开辟内存空间
	Lnode *node = NULL;                    //  定义新结点
	int count = 0;                          //  创建结点的个数
	head->next = NULL;              
	node = head->next;              	//  将最后一个结点的指针域永远保持为NULL
	printf("Input the node number: ");
	scanf("%d", &count);
	for (int i = 0; i < count; i++) {
		node = (Linklist)malloc(sizeof(Lnode));     //  为新结点开辟内存空间
		node->data = i;               //  为新结点的数据域赋值
		node->next = head->next;          //  将头指针所指向的下一个结点的地址,赋给新创建结点的next 
		head->next = node;          //  将新创建的结点的地址赋给头指针的下一个结点
	}
	return head;
}

头插法的核心所在是要理解这部分

	node->next = head->next;          //  将头指针所指向的下一个结点的地址,赋给新创建结点的next 
	head->next = node;          //  将新创建的结点的地址赋给头指针的下一个结点

会发现,头插法创建链表时候,就相当于后来居上。 后面的结点不断往前插,而最后创建的结点在第一个结点处, 第一个创建的结点变成了尾结点

(2)尾插法
在这里插入图片描述

void CreatByRear(LinkList head)
{
	Node *r,*s;
	char name[20];
	int number;
	r=head;//r指向头结点 
	printf("请输入姓名和学号:\n");
	while(1)
	{
		scanf("%s",name);
		scanf("%d",number);
		if(number==0)
		{
			break;
		}
		s=(Node *)malloc(sizeof(Node));//分配结点的内存空间
		strcpy(s->name,name);
		s->number=number;
		r->next=s;//原来的结点指向新结点
		r=s;//r指向新结点 
	}
	r->next=NULL;//链表的尾结点指针为空 
}//CreatByRear函数的功能是创建链表,在该函数中首先定义需要用的指针变量r和s,r指向当前链表的表尾结点,s指向新创建的结点

核心所在是这部分
在这里插入图片描述

头插法相对简便,但插入的数据与插入的顺序相反;
尾插法操作相对复杂,但插入的数据与插入顺序相同。

链表的销毁

从前往后销毁如下
在这里插入图片描述

先让p指向,头结点后面那个第一个有效节点。 (红色箭头的p)
然后把头结点的next值修改成,现在第一个有效节点的next成员的值(蓝色的箭头)
然后再释放p,这样不会使链表中途断开,一直删完。当删到最后一个时,head->next变为NULL,销毁正式结束。

void destroy(point *head)
{
	point *p;
	while (head->next)
	{
		p = head->next;
		head->next = p->next;
		free(p);
	}
}

链表的查找

有三个参数(point head, int oldrows, int oldcols)
从前往后用一个指针分别指向链表的每一个结构体判断oldrows和oldcols是否相等
我们不管以后的插入删除听起来是想要这个点的位置,其实最重要的是找到他的前驱结点
找到它的前驱结点才能把它"架空",修改掉前驱结点的next值,然后才可以大方的把它的空间释放
需要两个指针:一个负责查找的指针,一个负责记录前驱结点的指针

红色为循环开始,蓝色为循环一次的结果
在这里插入图片描述

for (p = head.next; p && ((p->cols != oldcols) || (p->rows != oldrows)); p = p->next)
	q = p;

在这里插入图片描述
用程序实现

point *found(point head, int oldrows,int oldcols)
{
point *p;
point *q = NULL;
for (p = head.next; p && ((p->cols != oldcols) || (p->rows != oldrows)); p = p->next)
q = p;
return q;
//若指定点为第一个,返回值为NULL
//若指定点为除了第一个以外的其他节点,则该函数的返回值为目标的前一个指定点。
//若指定点不存在,则该函数的返回值指向末节点。
}

链表的插入

思想:定位到它的前驱结点,然后改变它的前驱结点的值,让它指向需要插入的结构体,然后把原始的前驱结点的NEXT赋值给你新插入进来的结构体

q指针是查找返回的值,p指针是新开辟地址,红色是初始指向,蓝色是程序结束的指向。
在这里插入图片描述
核心思想代码

if (q == NULL)  //新点插入到头结点的后面(原来第一个有效节点前面)
{  
p->next = head->next;
head->next = p;
}
else if (q->next==NULL)  //指定点不存在,应补充在链表的后面。
{
        p->next = q->next;
q->next = p;
}
else
{
p->next = q->next;
q->next = p;
}
//这段3段程序明显都是一个算法,可以进行简化,
if (NULL == pro)
{
	q = head;
}
p->next = q->next;
q->next = p;

程序实现

void insert(point *head)   //采用左插入节点方式
{
	int newrows;
	int newcols;
	int oldrows;
	int oldcols;
	point *p;
	point *pro;
	showtopic("\n当前坐标如下,请参考插入位置进行左插入\n");
	showpoints(*head);
	showtopic("\n请输入将要插入的位置\n");
	scanf("%d %d", &oldrows, &oldcols);
	fflush(stdin);
	pro = found(*head, oldrows, oldcols);
	showtopic("\n请输入你要插入的数据\n");
	scanf("%d %d", &newrows, &newcols);
	fflush(stdin);
	p = create(newrows, newcols);
	if (NULL == pro)
	{
		pro = head;
	}
	p->next = pro->next;
	pro->next = p;
}

链表的删除

先想办法把你要删的元素从链表上剔除,然后让链表仍然连续。
在这里插入图片描述

步骤
1.让p指向目标节点的前驱结点(如果是第一个点的话,p=head->next)
2.把q->next的值赋值为p所指向实例的next成员,然后p所指向的成员就被“架空”了。
3.释放p的空间。

程序实现

void *delete(point *head)
{
	int rows;
	int cols;
	point *p;
	point *pro;
	showpoints(*head);
	showtopic("\n请输入你所需要删除节点的rows和cols值\n");
	scanf("%d %d", &rows, &cols);
	fflush(stdin);
	pro = found(*head, rows, cols);
	if (pro && pro->next == NULL)        //这种表达式,如果前面为假后面直接都不用看了,如果你调换了他两个的条件的位置,会引发一个bug。
	{
		showtopic("\n要删除的节点不存在(按任意键继续....)\n");
		getch();
	}
	else
	{
		if (NULL == pro)
		{
			pro = head;
		}
		p = pro->next;
		pro->next = p->next;
		free(p);
		showpoints(*head);
		showtopic("\n删除成功!!!!(按任意键继续)");
		getch();
	}
	return pro;
}

总结

要理解链表的各个结点连接方式,在完成对链表的一系列操作时,要先查找到目标结点的前驱结点,然后通过改变该节点的指向来实现操作。因此要充分理解和掌握链表的查找。链表这一内容,应用到了结构体和指针,要掌握好链表,还需要掌握好指针与结构体的相关知识。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构单链表插入、删除和修改实验报告 一、实验目的 1.理解数据结构中带头结点单链表的定义和逻辑图表示方法。 2.掌握单链表中结点结构的JAVA描述。 3.熟练掌握单链表的插入、删除和查询算法的设计与JAVA实现。 4.熟练掌握简单的演示菜单与人机交互设计方法。 二、实验内容 1. 编制一个演示单链表插入、删除、查找等操作的程序。 三、实验步骤 1.需求分析 本演示程序用JAVA编写,完成单链表的生成,任意位置的插入、删除,以及确定某一元素在单链表中的位置。 ① 输入的形式和输入值的范围:插入元素时需要输入插入的位置和元素的值;删除元素时输入删除元素的位置;查找操作时需要输入元素的值。在所有输入中,元素的值都是整数。 ② 输出的形式:在所有三种操作中都显示操作是否正确以及操作后单链表的内容。其中删除操作后显示删除的元素的值,查找操作后显示要查找元素的位置。   ③ 程序所能达到的功能:完成单链表的生成(通过插入操作)、插入、删除、查找操作。 ④ 测试数据:  A. 插入操作中依次输入11,12,13,14,15,16,生成一个单链表    B. 查找操作中依次输入12,15,22返回这3个元素在单链表中的位置    C. 删除操作中依次输入2,5,删除位于2和5的元素 2.概要设计 1)为了实现上述程序功能,需要定义单链表的抽象数据类型:   ADT LinkList {    数据对象:D={ai|ai∈IntegerSet,i=0,1,2,…,n,n≥0}    数据关系:R={|ai,ai+1 ∈D}    基本操作: (1)insert 初始化状态:单链表可以不为空集;操作结果:插入一个空的单链表L。   (2)decelt     操作结果:删除已有的单链表的某些结点。 (3)display     操作结果:将上述输入的元素进行排列显示。    (4)modify     操作结果:将上述输入的某些元素进行修改。    (5)save     操作结果:对上述所有元素进行保存。    (6)load     操作结果:对上述元素进行重新装载。   }   2)本程序包含7个函数:   ① 主函数main()   ② 保存单链表函数save()   ③ 重载操作菜单函数load()   ④ 显示单链表内容函数display ()   ⑤ 插入元素函数insert ()   ⑥ 删除元素函数decelt ()   ⑦ 修改元素函数modify()   各函数间关系如下: 3.详细设计   实现概要设计中定义的所有的数据类型,对每个操作给出伪码算法。对主程序和其他模块也都需要写出伪码算法。   1) 结点类型和指针类型   typedef struct node {    int data;    struct node *next;   }Node,*singleLIST.java;   2) 单链表的基本操作   为了方便,在单链表中设头结点,其data域没有意义。 bool insert(singleLIST) (伪码算法)   bool modify(singleLIST) (伪码算法)   void delect(singleLIST)   (伪码算法)   void display()   (伪码算法) 3) 其他模块伪码算法 4.调试分析   (略) 5.使用说明 程序名为 ,运行环境为Windows。程序执行后显示   ========================   0----EXIT   1----INSERT   2----DELETE   3----DISPLAY 4----MODIFY 5----EXIST =======================   SELECT:   在select后输入数字选择执行不同的功能。要求首先输入足够多的插入元素,才可以进行其他的操作。每执行一次功能,就会显示执行的结果(正确或错误)以及执行后单链表的内容。 选择5:退出程序   选择1:显示"INSERT =" ,   要求输入要插入的位置和元素的值(都是整数)。   选择2:显示"DELETE =" ,   要求输入要删除元素的位置,执行成功后返回元素的值。   选择3:显示"MODIFY = " , 选择要修改的对象,执行成功后返回新的元素值。 选择4:显示"DIAPLAY= "   显示所有单链表中的元素,自动进行排序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值