C语言单链表实现19个功能完全详解
单链表的基本操作

10)调用头插法的函数,分别输入10,20,分别回车:
11)调用尾插法的函数,分别输入30,40
12)查找单链表的第四个元素:
13)主函数中传入参数,删除单链表的第一个结点:
14)主函数传入参数,删除第0个未位置的元素,程序报错:
15)最后,输出单链表中的元素:
return 0;
}
6)编译,连接,运行源代码:
7)输入8,回车,并输入8个数,用空格分隔开,根据输出信息,可以看出,链表已经拆分为两个
五、实验总结
1.单链表采用的是数据+指针的表示形式,指针域总是指向下一个结
点(结构体)的地址,因此,在内存中的地址空间可以是不连续的,操作比顺序存储更加的方便
2.单链表使用时,需要用malloc函数申请地址空间,最后,删除元
素时,使用free函数释放空间。
c语言中链表的定义

c语言中链表的定义C语言中链表的定义链表是一种常用的数据结构,它是由一系列节点组成的,每个节点包含一个数据元素和一个指向下一个节点的指针。
链表可以用来存储任意类型的数据,而且它的大小可以动态地增加或减少,非常灵活。
在C语言中,链表的定义通常包括两个部分:节点结构体和链表结构体。
节点结构体定义如下:```typedef struct node {int data; // 数据元素struct node *next; // 指向下一个节点的指针} Node;```这里定义了一个名为Node的结构体,它包含两个成员变量:data和next。
其中,data用来存储节点的数据元素,next用来指向下一个节点的指针。
注意,这里的next是一个指向Node类型的指针,这样才能实现链表的连接。
链表结构体定义如下:```typedef struct list {Node *head; // 指向链表头节点的指针Node *tail; // 指向链表尾节点的指针int size; // 链表的大小} List;```这里定义了一个名为List的结构体,它包含三个成员变量:head、tail和size。
其中,head和tail分别指向链表的头节点和尾节点,size表示链表的大小。
通过这两个结构体的定义,我们就可以创建一个链表了。
下面是一个简单的例子:```int main() {List list = {NULL, NULL, 0}; // 初始化链表Node *node1 = (Node*)malloc(sizeof(Node)); // 创建第一个节点node1->data = 1; // 设置节点的数据元素node1->next = NULL; // 设置节点的指针list.head = node1; // 将节点1设置为链表的头节点list.tail = node1; // 将节点1设置为链表的尾节点list.size++; // 链表大小加1// 创建更多的节点...return 0;}```在这个例子中,我们首先初始化了一个空链表,然后创建了第一个节点,并将它设置为链表的头节点和尾节点。
单链表结构体定义

单链表结构体定义单链表是一种常见的数据结构,它由一系列节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。
在C语言中,可以使用结构体来定义单链表的节点。
我们需要定义一个表示单链表节点的结构体。
该结构体包含两个成员变量:一个用于存储数据的数据域,和一个指向下一个节点的指针域。
```struct ListNode {int data; // 数据域struct ListNode* next; // 指针域};```接下来,我们可以使用该结构体来创建单链表。
首先,我们需要定义一个指向链表头节点的指针。
```struct ListNode* head = NULL;```在链表为空时,头指针指向NULL。
当我们向链表中插入新的节点时,需要进行一些操作。
我们需要创建一个新的节点,并为其分配内存空间。
```struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));```然后,我们可以给新节点的数据域赋值。
```newNode->data = value;```接下来,我们需要将新节点插入到链表中。
如果链表为空,那么新节点将成为链表的头节点。
```if (head == NULL) {head = newNode;newNode->next = NULL;}```如果链表不为空,我们需要将新节点插入到链表的末尾。
```struct ListNode* current = head;while (current->next != NULL) {current = current->next;}current->next = newNode;newNode->next = NULL;```通过以上操作,我们可以将新节点成功插入到链表中。
如果我们想要插入节点的位置不是链表末尾,而是中间的某个位置,我们同样可以根据需要进行相应的操作。
链表c语言经典例题

链表c语言经典例题
链表是计算机科学中的经典数据结构之一,常用于存储和操作动态数据。
以下是一些常见的链表例题,可以帮助理解链表的基本操作和应用。
1. 链表的创建:
- 创建一个空链表。
- 创建一个包含指定节点值的链表。
2. 链表的插入操作:
- 在链表的头部插入一个节点。
- 在链表的尾部插入一个节点。
- 在指定位置插入一个节点。
3. 链表的删除操作:
- 删除链表的头节点。
- 删除链表的尾节点。
- 删除指定数值的节点。
4. 链表的查找操作:
- 查找链表中指定数值的节点。
- 查找链表的中间节点。
5. 链表的逆序操作:
- 反转整个链表。
- 反转链表的前 N 个节点。
- 反转链表的一部分区间内的节点。
6. 链表的合并操作:
- 合并两个有序链表,使其有序。
- 合并 K 个有序链表,使其有序。
7. 链表的环检测:
- 判断链表中是否存在环,若存在,则返回环的起始节点。
8. 链表的拆分操作:
- 将一个链表按照奇偶位置拆分成两个链表。
以上是一些链表的经典例题,通过解答这些例题,可以加深对链表结构和基本操作的理解。
在编写对应的 C 语言代码时,需要注意链表节点的定义、指针的使用以及内存的动态分配和释放等问题。
实验四 链表

实验二链表的基本操作一、实验目的掌握链表的基本概念、结构的定义,通过设计程序掌握链表上的基本操作:建立、插入、删除、查找以及链表合并等,并理解线性表的两种存储结构:顺序表和链表的区别。
二、实验准备1. 复习C语言中指针的用法,特别是结构体的指针的用法。
2. 了解链表(含带头结点的链表、循环链表)的概念,链表的结构定义方法。
单链表是线性表的链式存储表示,是用一组任意的存储单元依次存储线性表的数据元素。
因此,为了表示每个数据元素a i与其直接后继元素a i+1之间的逻辑关系,对数据元素a i来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置),而这部分就是用指针来完成的。
3. 掌握线性表在链式存储结构上实现基本操作:建立、查找、插入、删除等算法。
在实现这些算法的时候,要注意判断输入数据的合法性,除此之外还要要注意以下内容:✧在实现查找的时候,首先要判断该顺序表是否为空,其次要判断查找后的结果(查到时输出查到的数据,未查到时给出相关提示)。
✧在实现插入的时候,由于是链式存储,它可以随机产生和回收存储空间,所以它不要判断线性表是否为满,但仍需判断要插入的位置是否合法,原因同实验一,其次要注意插入的时候语句的顺序不可颠倒,否则出错。
例如:ps所指向结点要插入在p所指向的结点之后,则:正确形式:s->next=p->next; p->next=s;错误形式:p->next=s;s->next=p->next(因为此时p->next已经指向s了)在实现删除的时候,首先要判断线性表是否为空,为空则不能删除;其次在删除后要回收空间。
例如:删除如上图所示s所指向的结点p->next=p->next->next;free(s);4. 链表部分相关操作代码:⑴单链表的结构定义:#include <stdio.h>typedef int elemtype;typedef struct lnode{ elemtype data;struct lnode *next;}*linklist;⑵建立单链表的算法int n; /*n作为整个程序的全局变量*/linklist *creat(void){ linklist *head, *p1, *p2;n=0;p1=p2=(linklist *)malloc(sizeof(linklist));scanf(“%d”,&p1->data);head=null;while(p1->data!=0){ n=n+1;if(n==1) head=p1;else p2->next=p1;p2=p1;p1=(linklist *)malloc(sizeof(linklist));scanf(“%d”,&p1->data);}p2->next=null;return(head);}⑶单链表的插入算法int insert(linklist *head, int i,elemtype e) { linklist *p, *s;int j;p=head; j=0;while(p && j<i-1){ p=p->next;++j;}if(!p||j>i-1){ printf(“无法插入”);return 0;}s=(linklist *)malloc(sizeof(lnode));s->data=e;s->next=p->next;p->next=s;return 1;}⑷单链表的删除算法int deltree(linklist *head,int i,elemtype e){ linklist *p, *q;int j;lp=head; j=0;while(p->next && j<i-1){ p=p->next;++j;}if(!(p->next)||j>i-1){ printf(“无法删除”);return 0;}q=p->next;p->next=q->next;e=q->data;free(q);return 1;}三、实验内容1. /*函数link()的功能是将带头结点的单链表l2链接到l1的后面,程序中存在几处错误,请改正并调试运行*/#include "linklist.h"void link(linklist l1,linklist l2){linklist p,q;p=l1;while (p->next)p=q->next;q=l2;p->next=q;free(l2);}void main(){ linklist l1,l2;l1=creat2(); /*生成带头结点的单链表l1*/print(l1); /*输出单链表l1*/l2=creat2(); /*生成带头结点的单链表l2*/print(l2); /*输出单链表l2*/link(l1,l2); /*将单链表l2链接到l1的后面*/print(l1); /*输出单链表l1*/}2./* 编写一个函数perm,将带头结点单链表中的所有值为奇数的结点集中到链表的左边,值为偶数的结点集中到链表的右边*/#include "linklist.h"linklist perm(linklist head){linklist pre,p;pre=head;p=head->next;while (p && p->data%2==1){ pre= p ;p= p->next ;}while (p){ if (p->data%2==1){ pre->next=p->next;p->next=head->next;head->next=p;p=pre->next;}else{ pre=p;p=p->next;}}}/*主函数,请勿改动,请将perm中的函数补充完整*/int main(){ linklist head;head=creat2(); /*尾插法建立单链表*/print(head); /*输出单链表head*/perm(head);print(head);delList(head);return 0;}3.设计程序:/*建立一个带头结点的单链表,然后将该链表进行倒置。
数据结构单链表实验报告

数据结构单链表实验报告一、实验目的1、深入理解单链表的数据结构及其基本操作。
2、掌握单链表的创建、插入、删除、查找等操作的实现方法。
3、通过实际编程,提高对数据结构和算法的理解和应用能力。
二、实验环境1、操作系统:Windows 102、编程语言:C 语言3、开发工具:Visual Studio 2019三、实验原理单链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据域和指针域。
指针域用于指向下一个节点,从而形成链表的链式结构。
单链表的基本操作包括:1、创建链表:通过动态分配内存创建链表的头节点,并初始化链表为空。
2、插入节点:可以在链表的头部、尾部或指定位置插入新的节点。
3、删除节点:根据给定的条件删除链表中的节点。
4、查找节点:在链表中查找满足特定条件的节点。
四、实验内容(一)单链表的创建```cinclude <stdioh>include <stdlibh>//定义链表节点结构体typedef struct Node {int data;struct Node next;} Node;//创建单链表Node createList(){Node head =(Node)malloc(sizeof(Node));if (head == NULL) {printf("内存分配失败!\n");return NULL;}head>data = 0;head>next = NULL;return head;}int main(){Node list = createList();//后续操作return 0;}```在创建单链表时,首先为头节点分配内存空间。
若内存分配失败,则提示错误信息并返回`NULL`。
成功分配内存后,初始化头节点的数据域和指针域。
(二)单链表的插入操作插入操作分为三种情况:头部插入、尾部插入和指定位置插入。
1、头部插入```cvoid insertAtHead(Node head, int data) {Node newNode =(Node)malloc(sizeof(Node));if (newNode == NULL) {printf("内存分配失败!\n");return;}newNode>data = data;newNode>next = head>next;head>next = newNode;}```头部插入时,创建新节点,将新节点的数据域赋值,并将其指针域指向原头节点的下一个节点,然后更新头节点的指针域指向新节点。
数据结构-链表

链表一种数据结构的链接实现是指按链式存储方式构建其存储结构,并在此链式存储结构上实现其基本运算。
线性表的常见链式存储结构有单链表、循环链表和双链表,其中最简单的单链表。
本节讨论单链表的组织方法以及线性表的基本运算在单链表上的实现。
单链表示法的基本思想是用指针表示结点间的逻辑关系。
因此单链表的一个存储结点包含两个部分,结点形式如下:其中,data部分称为数据域,用于存储线性表的一个数据元素。
next部分称为指针域或链域,用于存放一个指针,该指针指向本结点所含数据元素的直接后继所在的结点。
从上述单链表中可以联想到我们生活中的火车,还有一种火车只有火车头。
假设数据元素的类型为Datatype。
单链表的类型定义如下:typedef struct node{Datatype data;struct node * next;} node,* LinkList;struct node表示链表的结点,一个结点是由两个域数据域data和指针域next组成的记录(每个域实际上相当于一个变量),而next本身又是一个pointer类型的指针型变量。
这个定义与上面给出的单链表的结点形式一致。
单链表的简单操作:1、初始化建立一个空表。
空表由一个头指针和一个头结点(该结点同时也是尾结点)组成。
LinkList Initiate_LinkList()/* 建立一空表 */{ LinkLis head;head= malloc(sizeof(node));head -> next = NULL;return head;}2、定位:按值查找。
按从前往后的顺序,依次比较单链表中各表结点数据域的值与给定值X,第一个值与X相等的表结点的序号就是结果。
若没有这样的结点,运算结果为0。
int Locate_LinkList(LinkList head,Datatype x){ Node *p;p = head; /* 置初值 */p=p->next;j = 0; /* 置初值 */while((p!= NULL)&&(p -> data != x)){ p = p -> next;j ++;} /* 未达尾结点又未找到等于x的结点时继续扫描 */if (p -> data == x)return(j+1);elsereturn(0);}3、插入:把新的结点x插入到i结点之前。
c语言链表尾删法

c语言链表尾删法在C语言中,链表尾删法指的是删除链表中的最后一个节点。
下面是一个基本的示例,展示了如何在单链表中实现尾删法:首先,定义链表节点的结构体:c复制代码:#include <stdio.h>#include <stdlib.h>typedef struct Node {int data;struct Node* next;} Node;接下来,我们创建一个函数来删除链表的最后一个节点:c复制代码:void deleteLastNode(Node** head) {if (*head == NULL) {printf("链表为空,无法删除最后一个节点。
\n");return;}Node* temp = *head;Node* prev = NULL;// 如果链表只有一个节点if (temp->next == NULL) {*head = NULL;free(temp);return;}// 查找倒数第二个节点while (temp->next != NULL) {prev = temp;temp = temp->next;}// 删除最后一个节点prev->next = NULL;free(temp);}然后,我们可以创建一个简单的函数来向链表中添加节点,并测试尾删法:c复制代码:void appendNode(Node** head, int data) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->data = data;newNode->next = NULL;if (*head == NULL) {*head = newNode;} else {Node* temp = *head;while (temp->next != NULL) {temp = temp->next;}temp->next = newNode;}}void printList(Node* head) {Node* temp = head;while (temp != NULL) {printf("%d ", temp->data);temp = temp->next;}printf("\n");}int main() {Node* head = NULL;// 添加节点到链表appendNode(&head, 1); appendNode(&head, 2); appendNode(&head, 3); appendNode(&head, 4);printf("原始链表: ");printList(head);// 删除最后一个节点deleteLastNode(&head);printf("删除最后一个节点后的链表: "); printList(head);return 0;}这个示例展示了如何在C语言中实现链表的尾删法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
if(NULL == pHead)
{
printf("modifyElem函数执行,链表为空\n");
}
if(pos < 1)
{
printf("modifyElem函数执行,pos值非法\n");
return 0;
}
while(pHead !=NULL)
{
++i;
if(i == pos)
return 1;
}
/* 10.向单链表的表头插入一个元素 */
int insertHeadList(Node **pNode,elemType insertElem)
{
Node *pInsert;
pInsert = (Node *)malloc(sizeof(Node));
memset(pInsert,0,sizeof(Node));
{
printf("getElement函数执行,pos值超出链表长度\n");
return 0;
}
return pHead->element;
}
/* 8.从单链表中查找具有给定值x的第一个元素,若查找成功则返回该结点data域的存储地址,否则返回NULL */
elemType *getElemAddr(Node *pHead, elemType x)
/* 10.向单链表的表头插入一个元素 */
/* 11.向单链表的末尾添加一个元素 */
/* 12.向单链表中第pos个结点位置插入元素为x的结点,若插入成功返回1,否则返回0 */
/* 13.向有序单链表中插入元素x结点,使得插入后仍然有序 */
/* 14.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停止程序运行 */
return size; //链表的实际长度
}
/* 6.检查单链表是否为空,若为空则返回1,否则返回0 */
int isEmptyList(Node *pHead)
{
if(pHead == NULL)
{
printf("isEmptyList函数执行,链表为空\n");
return 1;
}
printf("isEmptyList函数执行,链表非空\n");
{
if(pHead == NULL) //空表,接入表头
{
pHead = p1;
}
else
{
p2->next = p1; //非空表,接入表尾
}
p2 = p1;
p1=(Node *)malloc(sizeof(Node)); //再重申请一个节点
if(p1 == NULL || p2 ==NULL)
void initList(Node **pNode)
{
*pNode = NULL;
printf("initList函数执行,初始化成功\n");
}
/* 2.创建线性表,此函数输入负数终止读取数据*/
Node *creatList(Node *pHead)
{
Node *p1;
Node *p2;
p1=p2=(Node *)malloc(sizeof(Node)); //申请新节点
pInsert->element = insertElem;
while(pHead->next != NULL)
{
pHead = pHead->next;
}
pHead->next = pInsert; //将链表末尾节点的下一结点指向新添加的节点
*pNode = pTmp;
printf("insertLastList函数执行,向表尾插入元素成功\n");
{
Node *pInsert;
Node *pHead;
Node *pTmp; //定义一个临时链表用来存放第一个节点
pHead = *pNode;
pTmp = pHead;
pInsert = (Node *)malloc(sizeof(Node)); //申请一个新节点
memset(pInsert,0,sizeof(Node));
}
if(pHead == NULL)
{
printf("getElement函数执行,链表为空\n");
return 0;
//exit(1);
}
while(pHead !=NULL)
{
++i;
if(i == pos)
{
break;
}
pHead = pHead->next; //移到下一结点
}
if(i < pos) //链表长度不足则退出
{
printf("内存分配失败\n");
exit(0);
}
memset(p1,0,sizeof(Node));
scanf("%d",&p1->element);
p1->next = NULL;
}
printf("creatList函数执行,链表创建成功\n");
return pHead; //返回链表的头指针
}
/* 5.返回单链表的长度 */
int sizeList(Node *pHead)
{
int size = 0;
while(pHead != NULL)
{
size++; //遍历链表size大小比链表的实际长度小1
pHead = pHead->next;
}
printf("sizeList函数执行,链表长度 %d \n",size);
/* 6.检查单链表是否为空,若为空则返回1,否则返回0 */
/* 7.返回单链表中第pos个结点中的元素,若pos超出范围,则停止程序运行 */
/* 8.从单链表中查找具有给定值x的第一个元素,若查找成功则返回该结点data域的存储地址,否则返回NULL */
/* 9.把单链表中第pos个结点的值修改为x的值,若修改成功返回1,否则返回0 */
pInsert->element = insertElem;
pInsert->next = *pNode;
*pNode = pInsert;
printf("insertHeadList函数执行,向表头插入元素成功\n");
return 1;
}
/* 11.向单链表的末尾添加一个元素 */
int insertLastList(Node **pNode,elemType insertElem)
if(p1 == NULL || p2 ==NULL)
{
printf("内存分配失败\n");
exit(0);
}
memset(p1,0,sizeof(Node));
scanf("%d",&p1->element); //输入新节点
p1->next = NULL; //新节点的指针置为空
while(p1->element > 0) //输入的值大于0则继续,直到输入的值为负
{
if(NULL == pHead)
{
printf("getElemAddr函数执行,链表为空\n");
return NULL;
}
if(x < 0)ห้องสมุดไป่ตู้
{
printf("getElemAddr函数执行,给定值X不合法\n");
return NULL;
}
while((pHead->element != x) && (NULL != pHead->next)) //判断是否到链表末尾,以及是否存在所要找的元素
/************************************************************************/
typedef struct Node{ /* 定义单链表结点类型 */
elemType element;
Node *next;
}Node;
/* 1.初始化线性表,即置单链表的表头指针为空 */
{
pHead = pHead->next;
}
if((pHead->element != x) && (pHead != NULL))
{
printf("getElemAddr函数执行,在链表中未找到x值\n");
return NULL;
}
if(pHead->element == x)
{
printf("getElemAddr函数执行,元素 %d 的地址为 0x%x\n",x,&(pHead->element));
#include "stdafx.h"
#include "stdio.h"
#include <stdlib.h>
#include "string.h"
typedef int elemType ;
/************************************************************************/
/* 以下是关于线性表链接存储(单链表)操作的18种算法 */