单链表的存储与操作
数据结构实验报告--单链表
数据结构实验报告--单链表数据结构实验报告--单链表1.引言1.1 研究目的本实验旨在通过实践的方式,深入了解单链表的数据结构以及相关操作,提升对数据结构的理解和应用能力。
1.2 实验内容本实验主要包括以下几个方面的内容:●单链表的基本定义和实现●单链表的插入、删除、遍历操作●单链表的逆置操作●单链表的查找和修改操作2.理论基础2.1 单链表的定义单链表是一种常见的线性数据结构,它由一系列的节点组成,每个节点包含数据和指向下一个节点的指针。
2.2 单链表的基本操作①单链表的插入操作在单链表中,可以通过插入操作在指定位置插入一个新节点,该操作主要包括以下步骤:●创建一个新的节点,并为其赋值●将新节点的next指针指向插入位置的后一个节点●将插入位置的前一个节点的next指针指向新节点②单链表的删除操作在单链表中,可以通过删除操作删除指定位置的节点,该操作主要包括以下步骤:●将删除位置的前一个节点的next指针指向删除位置的后一个节点●释放删除节点的内存③单链表的遍历操作单链表的遍历操作主要是依次访问链表中的每一个节点,并执行相应的操作。
④单链表的逆置操作单链表的逆置操作可以将一个单链表中的节点顺序进行颠倒。
⑤单链表的查找操作在单链表中,可以通过查找操作找到指定值的节点。
⑥单链表的修改操作在单链表中,可以通过修改操作修改指定位置的节点的值。
3.实验过程3.1 实验环境本次实验使用C语言进行编程,需要先安装相应的编程环境,如gcc编译器。
3.2 实验步骤①单链表的创建和初始化首先创建一个空链表,并初始化链表的头指针。
②单链表的插入操作按照需求,在链表的指定位置插入一个新节点。
③单链表的删除操作按照需求,删除链表中的指定位置的节点。
④单链表的遍历操作依次访问链表中的每一个节点,并输出其值。
⑤单链表的逆置操作将单链表中的节点顺序进行逆置。
⑥单链表的查找操作按照需求,在链表中查找指定值的节点。
3.2.7 单链表的修改操作按照需求,修改链表中指定位置的节点的值。
PTA7-4单链表基本操作
PTA7-4单链表基本操作7-4 单链表基本操作请编写程序实现单链表插⼊、删除结点等基本算法。
给定⼀个单链表和⼀系列插⼊、删除结点的操作序列,输出实施上述操作后的链表。
单链表数据域值为整数。
输⼊格式:输⼊第1⾏为1个正整数n,表⽰当前单链表长度;第2⾏为n个空格间隔的整数,为该链表n个元素的数据域值。
第3⾏为1个正整数m,表⽰对该链表施加的操作数量;接下来m⾏,每⾏表⽰⼀个操作,为2个或3个整数,格式为0 k d或1 k。
0 k d表⽰在链表第k个结点后插⼊⼀个数据域值为d的结点,若k=0则表⽰表头插⼊。
1 k表⽰删除链表中第k个结点,此时k不能为0。
注:操作序列中若含有不合法的操作(如在长度为5的链表中删除第8个结点、删除第0个结点等),则忽略该操作。
n和m不超过100000。
输出格式:输出为⼀⾏整数,表⽰实施上述m个操作后的链表,每个整数后⼀个空格。
输⼊数据保证结果链表不空。
输⼊样例:51 2 3 4 550 2 80 9 60 0 71 01 6输出样例:7 1 2 8 3 5参照课本的实现#include<iostream>#include<iomanip>#include<stdlib.h>using namespace std;typedef int ElemType;typedef int Status;#define ERROR 0#define OK 1#define OVERFLOW 3typedef struct LNode{ElemType data;struct LNode *next;}LNode ,*LinkList;Status ListInsert(LinkList L,int i,ElemType e){int j=0;LinkList p=L,s;while(p&&j<i-1) // 寻找第i-1个结点{p=p->next;j++;}if(!p||j>i-1) // i⼩于1或者⼤于表长return ERROR;s=(LinkList)malloc(sizeof(LNode)); // ⽣成新结点s->data=e; // 插⼊L中s->next=p->next;p->next=s;return OK;}Status ListDelete(LinkList L,int i){int j=0;LinkList p=L,q;while(p->next&&j<i-1) // 寻找第i个结点,并令p指向其前趋{p=p->next;j++;}if(!p->next||j>i-1) // 删除位置不合理return ERROR;q=p->next; // 删除并释放结点p->next=q->next;free(q);return OK;}int main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);LinkList L;L=(LinkList)malloc(sizeof(LNode)); // 产⽣头结点,并使L指向此头结点 if(!L) // 存储分配失败exit(OVERFLOW);L->next=NULL;int n=0,m=0;LinkList db=L,da;cin>>n;for(int i=0;i<n;i++){da=(LinkList)malloc(sizeof(LNode));cin>>da->data;da->next=NULL;db->next=da;db = da;}cin>>m;for(int i=0;i<m;i++){int o,x,y;cin>>o;if(o==0){cin>>x>>y;ListInsert(L,x+1,y);}else if(o==1){cin>>x;ListDelete(L,x);}else{exit(ERROR);}}LinkList p=L->next;while(p!=NULL){cout<<p->data<<" ";p = p->next;}return 0;}。
单链表存储结构的概念
单链表存储结构的概念单链表(Singly Linked List)是一种常见的线性数据结构,用于存储一系列具有相同类型的元素。
它由一组称为节点(Node)的对象组成,每个节点包含了数据元素和一个指向下一个节点的引用(通常称为指针或链接)。
单链表的存储结构的概念如下:1.节点(Node):每个节点包含两个部分,一个是数据元素,用于存储实际的数据值;另一个是指向下一个节点的链接(指针),用于指示下一个节点的位置。
2.头节点(Head):单链表的起始节点称为头节点,它不包含实际的数据元素,只是用于标识整个链表的起点。
头节点通常是第一个具有数据元素的节点的前一个节点。
3.尾节点(Tail):单链表的结束节点称为尾节点,它是最后一个具有数据元素的节点。
尾节点的链接通常为空(null),表示链表的结束。
4.链表的连接方式:通过每个节点的链接(指针),单链表中的节点按顺序串联在一起,形成链表结构。
通过链接,可以迅速访问到链表中的下一个节点。
单链表的存储结构具有以下特点和优势:•动态性:单链表的长度可以在运行时动态改变,不需要事先指定链表的大小。
•灵活性:可以在链表中任意位置进行插入和删除操作,不需要移动其他节点的位置。
•存储效率:相对于数组,单链表可以节省存储空间,因为它不需要预留固定大小的连续存储空间。
•适用于频繁的插入和删除操作:由于链表的特点,插入和删除操作的时间复杂度为O(1),效率较高。
然而,单链表的访问和搜索操作的效率较低,需要从头节点开始遍历整个链表。
此外,由于每个节点需要额外的指针来存储下一个节点的地址,导致存储开销相对较高。
总的说来,单链表的存储结构使得它适用于需要频繁进行插入和删除操作而不关心随机访问的场景。
单链表基本操作的实现
单链表基本操作的实现单链表是一种常见的数据结构,它由多个节点组合而成,每个节点包含一个数据元素和一个指向下一个节点的指针。
通过指针,我们可以方便地在单链表中进行插入、删除和遍历等操作。
以下是关于单链表基本操作的实现。
1. 单链表的创建单链表的创建需要定义一个空的头结点,它的作用是方便在链表的头部进行添加和删除节点操作。
一个空的头节点可以在链表初始化的过程中进行创建。
```typedef struct Node{int data;struct Node *next;}Node;Node *createList(){Node *head = (Node*)malloc(sizeof(Node)); //创建空的头节点head->next = NULL;return head; //返回头节点的地址}```2. 单链表的插入单链表的插入可以分为在链表头部插入、在链表尾部插入和在链表中间插入三种情况。
a. 在链表头部插入节点:```void insertAtHead(Node *head, int data){Node *node = (Node*)malloc(sizeof(Node));node->data = data;node->next = head->next;head->next = node;}```b. 在链表尾部插入节点:```void insertAtTail(Node *head, int data){Node *node = (Node*)malloc(sizeof(Node));node->data = data;node->next = NULL;Node *p = head;while(p->next != NULL){p = p->next;}p->next = node;}```c. 在链表中间插入节点:```void insertAtMid(Node *head, int data, int pos){ Node *node = (Node*)malloc(sizeof(Node)); node->data = data;node->next = NULL;Node *p = head;int count = 0;while(p->next != NULL && count < pos-1){ p = p->next;count++;}if(count == pos-1){node->next = p->next;p->next = node;}else{printf("插入位置错误!");}}```3. 单链表的删除单链表的删除可以分为在链表头部删除、在链表尾部删除和在链表中间删除三种情况。
单链表数据结构
插入
if (p != NULL && j == i-1) { // 找到第i个结点
s = (LinkList) malloc ( sizeof (LNode)); // 生成新结点
s->data = e;
// 数据域赋值
s->next = p->next; //新结点指针指向后一结点
p->next = s; return OK;
6、销毁
4.6 销毁操作
while(L) { p = L->next; free(L); L=p;
// p指向第一结点(头节点为“哑结点”) // 释放首结点 // L指向p
}
// 销毁完成后,L为空(NULL)
算法的时间复杂度为:O(ListLength(L))
判空 求表长
4.7 其它操作
if(L->next==NULL) return TRUE; // 空
5、清空
4.5 清空操作
while (L->next) { p = L->next; L->next = p->next; free(p);
// p指向当前结点 // 头结点指向当前结点的后结点 // 释放当前结点内存
}
// 清空完成后,仍保留头结点L
算法的时间复杂度为:O(ListLength(L))
点。
5.1.2 逆序建立单链表
①建立一个带头结点的空单链表;
②输入数据元素ai,建立新结点p, 并把p插入在头结点之后成为第一个 结点。
③重复执行②步,直到完成单链表的 建立。
a1
a2 a1
创建出来的链表 点顺序与插入操作
顺序相反。
数据结构课件单链表
删除链表中的节点需要遍历至指定位置,时间复杂度为 O(n)。
查找节点
在链表中查找一个节点需要遍历整个链表,时间复杂度为 O(n)。
空间复杂度
空间占用
单链表的空间占用主要取决于链表中的 节点数,因此空间复杂度为O(n)。
VS
内存分配
每个节点需要分配内存空间存储数据和指 针,因此内存分配的空间复杂度也为O(n) 。
需要根据数据元素顺 序进行遍历的场景, 如排序算法等。
需要频繁插入、删除 操作的场景,如动态 规划、图算法等。
02
单链表的实现
创建单链表
定义节点结构体
首先需要定义一个节点结构体,包含 数据域和指针域两个部分,数据域用 于存储数据,指针域用于指向下一个 节点。
初始化头节点
创建一个头节点,并将其指针域指向 NULL,表示单链表的起始位置。
05
单链表常见问题与解决方 案
循环链表
总结词
循环链表是一种特殊类型的单链表,其中尾节点的指针指向头节点,形成一个闭环。
详细描述
在循环链表中,由于尾节点的指针指向头节点,因此遍历链表时需要特别注意,以避免无限循环。常见的解决方 法是在遍历时记录已经访问过的节点,避免重复访问。
链表中的重复元素
总结词
链表中可能存在重复元素的问题,这会影响数据处理的正确性。
详细描述
为了解决这个问题,可以在插入节点时检查新元素是否已存在于链表中。如果存在,则不进行插入操 作。另外,也可以使用哈希表等数据结构来快速查找重复元素。
链表的排序
总结词
对链表进行排序是常见的需求,但链表的排 序算法通常比数组的排序算法复杂。
合并单链表
总结词
将两个已排序的单链表合并为一个新的已排序的单链表。
数据结构实验题目
实验题目一一、单链表基本运算【问题描述】设计并实现线性表的单链表存储和运算。
【基本要求】实现单链表的插入、删除和遍历运算,每种操作用一个函数实现。
插入操作:将一个新元素插入表中指定序号的位置。
删除操作:将指定序号的元素从表中删除。
遍历操作:从表头按次序输入所有元素的值,若是空表,则输出信息“empty list!”。
【实现提示】程序运行时,首先在main函数中创建空的、带头结点的单链表。
然后多次调用实现插入操作的函数(每次都将元素在序号1位置上插入),将元素依次插入表中,最后调用实现遍历操作的函数输出所有元素。
之后再多次调用实现删除操作的函数将表还原为空表(每次都删除第1个元素,每删除一个元素后,将表中剩余元素都输出一次)。
【测试数据】输入数据:1 2 3 4 5 0(为0时结束,0不存入链表)第一次输出:5 4 3 2 1第二次输出:4 3 2 1第三次输出:3 2 1第四次输出:2 1第五次输出:1第六次输出:empty list!二、约瑟夫环问题【问题描述】编号为1,2,...,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
现在给定一个随机数m>0,从编号为1的人开始,按顺时针方向1开始顺序报数,报到m时停止。
报m的人出圈,同时留下他的密码作为新的m值,从他在顺时针方向上的下一个人开始,重新从1开始报数,如此下去,直至所有的人全部出列为止。
【基本要求】利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。
【测试数据】M的初始值为20;n等于7,7个人的密码依次为:3,1,7,2,4,8,4。
输出为:6,1,4,7,2,3,5【实现提示】程序运行时,首先要求用户指定初始报数上限值,然后读取各人的密码。
可设n≤30。
此题所用的循环链表中不需要“头结点”,请注意空表和非空表的界限。
【选作内容】用顺序存储结构实现该题目。
三、一元多项式相加、减运算器【问题描述】设计一个一元稀疏多项式简单计算器。
单链表的 基本操作
单向链表单向链表的基本操作,创建一个由6个节点组成的单向链表,显示链表中每个节点的数据,并且做增加、删除、查找节点以及计算单链表的长度等处理。
➢需求分析:1.功能(1)用尾插法创建一带头结点的由6个节点组成的单向链表:从键盘读入一组整数,作为单链表中的元素,输入完第6个结点后结束;将创建好的单链表元素依次输出到屏幕上。
(2)显示链表中每个节点的数据(3)从键盘输入一个数,查找在以上创建的单链表中是否存在该数;如果存在,显示它的位置,即第几个元素;如果不存在,给出相应提示如“No found node!”。
(4)在上述的单链表中的指定位置插入指定数据,并输出单链表中所有数据。
(5)删除上述单链表中指定位置的结点,并输出单链表中所有数据。
(6)求单链表的长度并输出.2.输入要求先输入单链表中结点个数n,再输入单链表中所有数据,在单链表中需查找的数据,需插入的数据元素的位置、值,要删除的数据元素的位置。
3。
测试数据单链表中所有数据:12,23,56,21,8,10在单链表中需查找的数据:56;24插入的数据元素的位置、值:1,28;7,28;0,28要删除的数据元素的位置:6➢概要设计:1.算法思想:由于在操作过程中要进行插入、删除等操作,为运算方便,选用带头结点的单链表作数据元素的存储结构.对每个数据元素,由一个数据域和一个指针域组成,数据域放输入的数据值,指针域指向下一个结点。
2.数据结构:单链表结点类型:typedef struct Liistnode {int data;struct Listnode *next;}NODE;3.模块划分:a)用尾插法建立带头结点的单链表*CreateList函数;b)显示链表中每个结点的数据PrintList函数;c)从键盘输入一个数,查找单链表中是否存在该数FoundList函数;d)在单链表中指定位置插入指定数据并输出单链表中所有数据InsertList函数;e)删除单链表中指定位置的结点并输出单链表中所有数据DeleteList函数;f)计算单链表的长度并在屏幕上输出LengthList函数;g)主函数main(),功能是给出测试数据值,建立测试数据值的带头结点的单链表,调用PrintList函数、FoundList函数、InsertList函数、DeleteList函数、LengthList函数实现问题要求。
单链表的基本操作
实验二:单链表的基本操作编写一个完整的程序,实现单链表的建立、插入、删除、输出等基本操作。
(1)建立一个带头结点的单链表。
(2)计算单链表的长度,然后输出单链表。
(3)查找值为x的直接前驱结点q。
(4)删除值为x的结点。
(5)把单向链表中元素逆置(不允许申请新的结点空间)。
(6)已知单链表中元素递增有序,请写出一个高效的算法,删除表中所有值大于mink且小于maxk的元素(若表中存在这样的元素),同时释放被删结点空间,并分析你的算法的时间复杂度(注意:mink和maxk是给定的两个参变量,他们的值可以和表中的元素相同,也可以不同)。
(7)同(6)的条件,试写一高效的算法,删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同),同时释放被删结点空间,并分析你的算法时间复杂度。
(8)利用(1)建立的链表,实现将其分解成两个链表,其中一个全部为奇数,另一个全部为偶数(尽量利用已知的存储空间)。
(9)在主函数中设计一个简单的菜单,分别测试上述算法。
# include <stdio.h># include <stdlib.h>typedef struct node{int data;struct node * next;}Lnode, * LinkList;int m=sizeof(Lnode);//建立新的链表void Bulid_List(LinkList root){int num;LinkList s,p;s=root->next;int n;printf("请输入新建链表的长度n数据:\n"); scanf("%d",&n);printf("请依次建立链表:");for(int i=0;i<n;i++){scanf("%d",&num);s->data=num;p=(LinkList)malloc(m);s->next=p;s=p;s->next=NULL;}printf("链表已建立!\n");}//对链表的输出,包括长度和元素void OutPut_list(LinkList root) {int len=0;LinkList s;s=root->next;if(s->next==NULL)printf("单链表无数据,请先新建单链表。
单链表的操作实现实验报告
题目来源:□√教材页题□√教师补充□自选题目
主要功能描述:链表的初始化、链表的创建(头部插入法、尾部插入法)、求表长、查找(按值查找、按序号查找)、插入、删除、输出、两个有序单链表的合并等。
设计分析:
初始化:为单链表申请头结点空间,将单链表设置为空;创建:(1)头部插入法:(a)初始化空表;(b)申请新结点并赋值;(c)插入新结点;(d)插入第i个元素。
break;
case'1':
puts("\n");
puts("*********************************************************");
puts("* 0---般创建1---头部插入法2---尾部插入法*");
puts("*********************************************************");
r->next=p;
r=p;
}
r->next=NULL;
return h;
}
/*头部插入*/
int CreatfromH(LinkList head)
{
LinkList p;
ElemType x;
puts("输入数据,输入-1000结束输入!");
while(1)
{
scanf("%d",&x);
if(x!=-1000)
while(p!=NULL)
{
printf("\n%d",p->data);
p=p->next;
实验二 单链表基本操作
实验二单链表基本操作一实验目的1.学会定义单链表的结点类型,实现对单链表的一些基本操作和具体的函数定义,了解并掌握单链表的类定义以及成员函数的定义与调用。
2.掌握单链表基本操作及两个有序表归并、单链表逆置等操作的实现。
二实验要求1.预习C语言中结构体的定义与基本操作方法。
2.对单链表的每个基本操作用单独的函数实现。
3.编写完整程序完成下面的实验内容并上机运行。
4.整理并上交实验报告。
三实验内容1.编写程序完成单链表的下列基本操作:(1)初始化单链表La。
(2)在La中第i个元素之前插入一个新结点。
(3)删除La中的第i个元素结点。
(4)在La中查找某结点并返回其位置。
(5)打印输出La中的结点元素值。
2 .构造两个带有表头结点的有序单链表La、Lb,编写程序实现将La、Lb合并成一个有序单链表Lc。
合并思想是:程序需要3个指针:pa、pb、pc,其中pa,pb分别指向La表与Lb表中当前待比较插入的结点,pc 指向Lc表中当前最后一个结点。
依次扫描La和Lb中的元素,比较当前元素的值,将较小者链接到*pc 之后,如此重复直到La或Lb结束为止,再将另一个链表余下的内容链接到pc所指的结点之后。
3.构造一个单链表L,其头结点指针为head,编写程序实现将L逆置。
(即最后一个结点变成第一个结点,原来倒数第二个结点变成第二个结点,如此等等。
)四思考与提高1.如果上面实验内容2中合并的表内不允许有重复的数据该如何操作?2.如何将一个带头结点的单链表La分解成两个同样结构的单链表Lb,Lc,使得Lb中只含La表中奇数结点,Lc中含有La表的偶数结点?1.编写程序完成单链表的下列基本操作:(1)初始化单链表La。
(2)在La中第i个元素之前插入一个新结点。
(3)删除La中的第i个元素结点。
(4)在La中查找某结点并返回其位置。
(5)打印输出La中的结点元素值。
#include<stdio.h>#include<stdlib.h>#include <malloc.h>#define OK 1#define ERROR 0typedef int Status;typedef int ElemType;//定义存储结构typedef struct Lnode{int data; /*每个元素数据信息*/struct Lnode *next; /*存放后继元素的地址*/} LNode,*LinkList;int main(){void Create_L(LinkList &L,int n);void Print_L(LinkList L);Status ListInsert_L(LinkList &L,int i,ElemType e);Status ListDelete_L(LinkList &L,int i,ElemType &e);Status Find_L(LinkList L,int e);LinkList La;//创建单链表Laint n;printf("请输入链表La中的元素个数:\n");scanf("%d",&n);Create_L(La,n);//初始化单链表printf("现在La中的元素为:\n");Print_L(La);printf("-------------------------------------\n\n");printf("现在准备插入元素,请输入插入位置及所插入元素的值\n");int i,e;scanf("%d %d",&i,&e);ListInsert_L(La,i,e);printf("插入后La中的元素为:\n");Print_L(La);printf("-------------------------------------\n\n");printf("现在准备删除元素,请输入删除位置\n");scanf("%d",&i);ListDelete_L(La,i,e);printf("删除后La中的元素为:\n");Print_L(La);printf("-------------------------------------\n\n");printf("请输入所要查找元素的值:\n");scanf("%d",&e);Find_L(La,e);printf("所要查找元素的位置为:%d\n",Find_L(La,e)); }void Create_L(LinkList &L,int n){int j=1;L=(LinkList)malloc(sizeof(Lnode));L->next =NULL;//先建立一个带头结点的单链线性表L for(int i=n;i>0;--i){LinkList p=(LinkList)malloc(sizeof(Lnode));printf("请输入链表La中的第%d个元素:\n",j++);scanf("%d",&p->data);p->next=L->next;L->next =p;}//(逆序实现)/*LinkList q=L;for(int i=1;i<=n;i++){LinkList p=(LinkList)malloc (sizeof(Lnode));q->next=p;p->next=NULL;q=q->next ;printf("请输入链表La中的第%d个元素:\n",i);scanf("%d",&p->data);}//(正序实现)*/}//初始化单链表//输出单链表void Print_L(LinkList L){LinkList p;p=L->next;while(p){printf("%d ",p->data );p=p->next;}printf("\n");}//在单链表L的第i个位置前插入元素eStatus ListInsert_L(LinkList &L,int i,ElemType e) {LinkList p=L;int j=0;while(p&&j<i-1){p=p->next; ++j;}if(!p||j>i-1) return ERROR;LinkList s=(LinkList)malloc(sizeof(LNode));s->data=e; s->next=p->next;p->next=s;return OK;} //ListInsert_L//删除单链表L中第i个位置上的元素Status ListDelete_L(LinkList &L,int i,ElemType &e) {LinkList p=L;int j=0;while( p->next && j<i-1){p=p->next; ++j;}if(!p->next||j>i-1) return ERROR;LinkList q=p->next; p->next=q->next;e=q->data;free(q);return OK;}//LinkDelete_L/*查找元素并返回位置*/Status Find_L(LinkList L,int e){LinkList p=L->next;int j=1;while(p->data!=e&&p->next){p=p->next;j++;}if(p->data==e) return j;else{printf("无当前元素\n");return ERROR;}if(!p){printf("无当前元素\n");return ERROR;}}//定位2 .构造两个带有表头结点的有序单链表La、Lb,编写程序实现将La、Lb合并成一个有序单链表Lc。
单链表的操作实验报告
单链表的操作实验报告《单链表的操作实验报告》在计算机科学领域,数据结构是非常重要的基础知识之一。
而单链表作为一种常见的数据结构,经常被用来存储和操作数据。
在本次实验中,我们将对单链表的操作进行实验,并撰写实验报告以总结和分享我们的实验结果。
实验目的:1. 了解单链表的基本概念和操作方法。
2. 掌握单链表的插入、删除、查找等操作。
3. 通过实际操作加深对单链表的理解和掌握。
实验环境:1. 编程语言:C/C++2. 开发环境:Visual Studio Code3. 实验工具:GCC编译器实验步骤:1. 定义单链表的结构体,并实现初始化、插入、删除、查找等操作的函数。
2. 编写测试用例,对单链表的各种操作进行测试。
3. 分析实验结果,总结操作的时间复杂度和空间复杂度。
4. 撰写实验报告,分享实验过程和结果。
实验结果:经过实验,我们成功实现了单链表的初始化、插入、删除、查找等操作,并对这些操作进行了充分的测试。
我们发现单链表的插入和删除操作的时间复杂度为O(1),而查找操作的时间复杂度为O(n),其中n为链表的长度。
这些结果与我们的预期相符合,说明我们对单链表的操作有了较好的掌握。
实验总结:通过本次实验,我们不仅加深了对单链表的理解,还提高了编程能力和数据结构的应用能力。
我们对单链表的操作有了更深入的了解,为以后在实际项目中应用单链表打下了良好的基础。
结语:单链表作为一种常见的数据结构,在实际应用中具有重要的作用。
通过本次实验,我们对单链表的操作有了更深入的了解,相信在以后的学习和工作中能够更好地应用和运用单链表。
希望本次实验报告能够对读者有所帮助,也欢迎大家对实验结果进行讨论和交流。
【头歌】单链表的基本操作
【头歌】单链表的基本操作
单链表是一种线性数据结构,由一系列节点组成,每个节点包含数据元素和一个指向下一个节点的指针。
以下是单链表的基本操作:
1. 插入操作:在单链表的指定位置插入一个新节点。
具体步骤如下:
找到要插入的位置的前一个节点;
将新节点插入到前一个节点和当前节点之间;
修改新节点的指针,使其指向当前节点;
修改前一个节点的指针,使其指向新节点。
2. 删除操作:删除单链表中的指定节点。
具体步骤如下:
找到要删除的节点的前一个节点;
将前一个节点的指针指向要删除的节点的下一个节点;
释放要删除的节点的内存。
3. 查找操作:在单链表中查找指定元素。
具体步骤如下:
从头节点开始遍历单链表;
找到与指定元素相等的节点;
返回该节点的位置。
4. 遍历操作:从头节点开始,依次访问单链表中的每个节点。
具体步骤如下:创建一个指针指向头节点;
依次访问指针所指向的每个节点,直到指针为空。
5. 打印操作:打印单链表中的所有元素。
具体步骤如下:
创建一个指针指向头节点;
依次打印指针所指向的每个节点的数据元素,直到指针为空。
以上是单链表的基本操作,通过这些操作可以对单链表进行各种操作,如插入元素、删除元素、查找元素等。
单链表的基本操作代码
单链表的基本操作代码单链表是一种常用的数据结构,它具有优秀的插入和删除性能,在数据存储和处理方面具有广泛的应用。
单链表的基本操作包含创建链表、插入节点、删除节点、查找节点等,下面是单链表的基本操作代码:1. 定义单链表结构体:typedef struct ListNode {int val;struct ListNode *next;} ListNode;2. 创建单链表:ListNode *createList(int arr[], int n) {ListNode *head = NULL, *tail = NULL, *p = NULL;for(int i = 0; i < n; i++) {p = (ListNode *)malloc(sizeof(ListNode));p->val = arr[i];p->next = NULL;if(head == NULL) {head = tail = p;} else {tail->next = p;tail = p;}}return head;}3. 插入节点:void insertNode(ListNode **head, int val, int pos) {ListNode *p = (ListNode *)malloc(sizeof(ListNode)); p->val = val;p->next = NULL;if(*head == NULL) {if(pos != 0) {printf("Invalid position\n");return;} else {*head = p;return;}}if(pos == 0) {p->next = *head;*head = p;} else {int i = 0;ListNode *q = *head;while(q != NULL && i < pos - 1) {q = q->next;i++;}if(q == NULL || i != pos - 1) {printf("Invalid position\n");return;}p->next = q->next;q->next = p;}}4. 删除节点:void deleteNode(ListNode **head, int pos) {if(*head == NULL) {printf("List is empty\n");return;}if(pos == 0) {ListNode *p = *head;*head = (*head)->next;free(p);} else {int i = 0;ListNode *p = *head, *q = NULL; while(p != NULL && i < pos) { q = p;p = p->next;i++;}if(p == NULL || i != pos) {printf("Invalid position\n");return;}q->next = p->next;free(p);}}5. 查找节点:ListNode *findNode(ListNode *head, int val) {ListNode *p = head;while(p != NULL) {if(p->val == val) {return p;}p = p->next;}return NULL;}单链表的基本操作是数据结构中最基础的部分,掌握好这些代码对于往后的学习和应用都会有很大的帮助。
单链表的存储密度 。
单链表的存储密度。
单链表是一种重要的数据结构,在计算机科学领域广泛应用。
它具有动态性、易于操作等优点,因此被广泛应用于数据结构、算法等方面。
单链表的存储密度是指链表每个节点存储的数据量,它对链表的性质、底层实现、使用效率等方面有很大影响。
本文将介绍单链表的存储密度及其影响,以及如何优化单链表的存储密度。
一、单链表的存储结构单链表是由节点组成的。
每个节点包含两个部分:数据域和指针域。
数据域存储节点的数据信息,指针域存储下一个节点的地址,实现链式存储。
单链表的起始节点称为头节点,其不存储任何数据,仅存储指向第一个节点的指针。
尾节点指向NULL,表示链表结束。
单链表的存储结构如下所示:typedef struct Node { ElemType data; //数据域 struct Node* next; //指针域 }Node;typedef Node* LinkList;二、单链表的存储密度单链表的存储密度是指链表每个节点的数据量,通常用字节(Byte)表示。
因为单链表是动态存储结构,每个节点的空间大小是固定的,但数据量却是动态变化的。
因此,单链表的存储密度是一个随数据量变化而变化的值。
在计算单链表的存储密度时,需要考虑以下几个因素:1、节点的数据域类型节点的数据域类型不同,占据的空间大小也不同。
比如,int类型占据4个字节,double类型占据8个字节,char类型占据1个字节等等。
2、编译器对内存对齐的处理编译器在分配内存时,会对内存对齐进行处理。
对于一个不对齐的数据,会造成额外的存储空间浪费。
比如,对于int类型,通常会在32位系统下按4个字节对齐,在64位系统下按8个字节对齐。
3、操作系统对内存分配的处理操作系统对内存分配也有一定的影响。
现代操作系统支持虚拟内存的分配,将物理内存映射为虚拟内存,使得应用程序可以使用更多的内存空间。
但是,虚拟内存分配会带来一定的性能损失。
在实际编程中,单链表的存储密度通常是固定的,但是要考虑到存储空间的利用率。
单链表实验总结
单链表实验总结单链表是一种常见的数据结构,用于存储有序的数据元素。
在这个实验中,我通过实现单链表的基本操作,如插入、删除和查找等,加深了对单链表的理解。
在实验中,我首先创建了一个单链表的类,并实现了构造函数。
然后,我实现了向链表中插入节点的操作。
插入节点时,我需要将新的节点的指针指向当前节点的下一个节点,然后将前一个节点的指针指向新的节点,从而完成节点的插入。
在实现删除节点的操作时,我需要找到要删除的节点的前一个节点,然后将前一个节点的指针指向要删除节点的下一个节点,从而将要删除的节点排除在链表之外。
我还实现了通过索引查找节点的操作。
在这个操作中,我需要从链表的头节点开始迭代,直到找到要查找的索引位置的节点。
通过实践,我发现单链表的插入和删除操作的时间复杂度都是O(n),其中n表示链表的长度。
在查找操作中,时间复杂度是O(n)。
总之,通过这个实验,我对单链表的原理和基本操作有了更深的理解。
我也学到了如何使用单链表来解决实际问题。
这个实验让我更加熟悉了链表的概念和操作,为我进一步深入学习数据结构和算法打下了基础。
除了实现基本的插入、删除和查找操作,我还尝试了一些其他的操作来进一步加深对单链表的理解。
首先,我实现了获取链表长度的操作。
通过遍历整个链表,我可以统计节点的数量来得到链表的长度。
这个操作的时间复杂度是O(n)。
接下来,我尝试实现了链表的反转操作。
通过调整节点的指针指向,我可以将链表的顺序颠倒过来。
这个操作的时间复杂度是O(n)。
另外,我实现了链表的判空和清空操作。
判空操作可以判断链表是否为空,即链表的头节点是否为空。
清空操作可以将链表中的所有节点都删除,使链表变为空链表。
最后,我尝试了一些高级操作,如链表的排序和链表的合并。
排序操作可以将链表中的节点按照一定的顺序重新排列,通常使用冒泡排序、选择排序或插入排序等算法实现。
合并操作可以将两个有序链表合并成一个更大的有序链表,通常使用归并排序的思想实现。
数据结构单链表实验报告
数据结构单链表实验报告实验目的:本实验的目的是通过实现单链表数据结构,加深对数据结构的理解,并掌握单链表的基本操作和算法。
实验内容:1、单链表的定义单链表由若干个节点组成,每个节点包含数据域和指针域,数据域存储具体数据,指针域指向下一个节点。
单链表的头指针指向链表的第一个节点。
2、单链表的基本操作2.1 初始化链表初始化链表时,将头指针置空,表示链表为空。
2.2 插入节点插入节点可以分为头插法和尾插法。
- 头插法:将新节点插入链表头部,新节点的指针域指向原头节点,头指针指向新节点。
- 尾插法:将新节点插入链表尾部,新节点的指针域置空,原尾节点的指针域指向新节点。
2.3 删除节点删除节点可以分为按位置删除和按值删除两种方式。
- 按位置删除:给定要删除节点的位置,修改前一节点的指针域即可。
- 按值删除:给定要删除节点的值,遍历链表找到对应节点,修改前一节点的指针域即可。
2.4 遍历链表遍历链表即按顺序访问链表的每个节点,并输出节点的数据。
2.5 查找节点查找节点可以分为按位置查找和按值查找两种方式。
- 按位置查找:给定节点的位置,通过遍历链表找到对应节点。
- 按值查找:给定节点的值,通过遍历链表找到第一个匹配的节点。
实验步骤:1、根据实验目的,定义单链表的结构体和基本操作函数。
2、实现初始化链表的函数,将头指针置空。
3、实现头插法或尾插法插入节点的函数。
4、实现按位置删除节点的函数。
5、实现按值删除节点的函数。
6、实现遍历链表的函数,输出节点的数据。
7、实现按位置查找节点的函数。
8、实现按值查找节点的函数。
9、设计实验样例,测试单链表的各种操作。
实验结果与分析:通过测试实验样例,我们可以验证单链表的各种操作是否正确。
如果出现异常情况,可通过调试找出问题所在,并进行修改。
单链表的操作时间复杂度与操作的位置有关,对于查找操作,时间复杂度为O(n);对于插入和删除操作,时间复杂度也为O(n)。
附件:1、单链表的定义和基本操作的源代码文件。
单链表的实现及其基本操作
单链表的实现及其基本操作结点的引⼊链表是⼀种链式存储结构,链式存储结构的特点是⽤⼀组任意的存储单元存储数据元素。
为了能正确表⽰数据元素之间的线性关系,需引⼊结点概念。
⼀个结点表⽰链表中的⼀个数据元素,节点中除了储存数据元素的信息,还必须存放指向下⼀个节点的的指针(单、双链表的最后⼀个节点除外,它们存储的是⼀个空指针NULL)结点的结构如下图所⽰:代码如下:1 typedef struct node{2int data;3struct node* pNext;4 }Node, *PNode;View Code注:这⾥假设结点中储存的是整型 (int) 的数据单链表由多个结点依次连接⽽成,我们不难想象出它结构:我们注意到:在第⼀个结点的前⾯多了⼀个头结点,这是为了处理空表的⽅便⽽引⼊的,它的指针指向链表的第⼀个结点,⽽它的data域不存放任何信息。
单链表的基本操作1.创建链表1 PNode createList()2 {3int len, value;45 PNode pHead = (PNode)(malloc(sizeof(Node)));6 PNode pTail = pHead;7 pTail->pNext = NULL;89 printf("请输⼊你要的节点个数:");10 scanf("%d", &len);11for(int i=1;i<=len;i++){12 printf("请输⼊第%d个节点的值:", i);13 scanf("%d", &value);1415 PNode pNew = (PNode)malloc(sizeof(Node));16 pNew->data = value;17 pTail->pNext = pNew;18 pTail = pNew;19 pTail->pNext = NULL;20 }2122return pHead;23 }View Code2.遍历链表void traverse(PNode pHead){printf("遍历结果为:\n");PNode pTra = pHead;while(pTra->pNext != NULL){printf("%d ", pTra->pNext->data);pTra = pTra->pNext;}printf("\n");}View Code3.判断链表是否为空1bool isEmpty(PNode pHead)2 {3if(pHead->pNext==NULL)4return true;5else6return false;7 }View Code4.链表长度1int length(PNode pHead)2 {3int len = 0;4while(pHead->pNext!=NULL){5 pHead = pHead->pNext;6 len++;7 }8return len;910 }View Code5.插⼊结点1bool insert(PNode pHead, int pos, int val)2 {3if(pos<1 || pos>length(pHead)){4return false;5 }else{6 PNode pInsert = pHead;7for(int i=1;i<pos;i++){8 pInsert = pInsert->pNext;9 }1011 PNode pNew = (PNode)malloc(sizeof(Node));12 pNew->data = val;13 pNew->pNext = pInsert->pNext;14 pInsert->pNext = pNew;1516return true;17 }1819 }View Code6.删除结点1bool del(PNode pHead, int pos)2 {3if(pos<1 || pos>length(pHead)){4return false;5 }else{6 PNode pDel = pHead;7for(int i=1;i<pos;i++){8 pDel = pDel->pNext;9 }1011if(pos==length(pHead)){12free(pDel->pNext);13 pDel->pNext = NULL;14 }else{15 PNode pNext = pDel->pNext->pNext;16free(pDel->pNext);17 pDel->pNext = pNext;18 }1920return true;2122 }232425 }View Code7.查找节点(1)按元素值查找1 PNode locate(PNode pHead, int value)2 {3 PNode p = pHead->pNext;4while(p&&p->data!=value){ //NULL 是 05 p = p->pNext;6 }7return p;8 }View Code(2)按序号查找1 PNode get(PNode pHead, int k)2 {3 PNode p = pHead;4for(int i=1;i<=k;i++){5 p = p->pNext;6 }7return p;89 }View Code完整代码1 #include<stdio.h>2 #include<stdlib.h>3 typedef struct node{4int data;5struct node* pNext;6 }Node, *PNode;78 PNode createList();9void traverse(PNode pHead);10bool isEmpty(PNode pHead);11int length(PNode pHead);12bool insert(PNode pHead, int pos, int val);13bool del(PNode pHead, int pos);14 PNode get(PNode pHead, int k); //按序号查找15 PNode locate(PNode pHead, int value);//按值查找 1617int main(void)18 {19//test2021return0;22 }2324 PNode createList()25 {26int len, value;2728 PNode pHead = (PNode)(malloc(sizeof(Node)));29 PNode pTail = pHead;30 pTail->pNext = NULL;3132 printf("请输⼊你要的节点个数:");33 scanf("%d", &len);34for(int i=1;i<=len;i++){35 printf("请输⼊第%d个节点的值:", i);36 scanf("%d", &value);3738 PNode pNew = (PNode)malloc(sizeof(Node));39 pNew->data = value;40 pTail->pNext = pNew;41 pTail = pNew;42 pTail->pNext = NULL;43 }4445return pHead;46 }474849void traverse(PNode pHead)50 {51 printf("遍历结果为:\n");52 PNode pTra = pHead;53while(pTra->pNext != NULL)54 {55 printf("%d ", pTra->pNext->data);56 pTra = pTra->pNext;57 }58 printf("\n");59 }6061bool isEmpty(PNode pHead)62 {63if(pHead->pNext==NULL)64return true;65else66return false;67 }6869int length(PNode pHead)70 {71int len = 0;72while(pHead->pNext!=NULL){73 pHead = pHead->pNext;74 len++;75 }76return len;7778 }7980bool insert(PNode pHead, int pos, int val)81 {82if(pos<1 || pos>length(pHead)){83return false;84 }else{85 PNode pInsert = pHead;86for(int i=1;i<pos;i++){87 pInsert = pInsert->pNext;88 }8990 PNode pNew = (PNode)malloc(sizeof(Node));91 pNew->data = val;92 pNew->pNext = pInsert->pNext;93 pInsert->pNext = pNew;9495return true;96 }9798 }99100bool del(PNode pHead, int pos)101 {102if(pos<1 || pos>length(pHead)){103return false;104 }else{105 PNode pDel = pHead;106for(int i=1;i<pos;i++){107 pDel = pDel->pNext;108 }109110if(pos==length(pHead)){111free(pDel->pNext);112 pDel->pNext = NULL;113 }else{114 PNode pNext = pDel->pNext->pNext;115free(pDel->pNext);116 pDel->pNext = pNext;117 }118119return true;120121 }122123124 }125126 PNode get(PNode pHead, int k)127 {128 PNode p = pHead;129for(int i=1;i<=k;i++){130 p = p->pNext;131 }132return p;133134 }135 PNode locate(PNode pHead, int value)136 {137 PNode p = pHead->pNext;138while(p&&p->data!=value){ //NULL 是 0 139 p = p->pNext;140 }141return p;142 }View Code。
数据结构中链表及常见操作
链表1 定义链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。
由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O(1)。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。
但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。
在计算机科学中,链表作为一种基础的数据结构可以用来生成其它类型的数据结构。
链表通常由一连串节点组成,每个节点包含任意的实例数据(data fields)和一或两个用来指向明上一个或下一个节点的位置的链接("links")。
链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的访问往往要在不同的排列顺序中转换。
而链表是一种自我指示数据类型,因为它包含指向另一个相同类型的数据的指针(链接)。
链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。
链表有很多种不同的类型:单向链表,双向链表以及循环链表。
2 结构2.1 单向链表链表中最简单的一种是单向链表,它包含两个域,一个信息域和一个指针域。
这个链接指向列表中的下一个节点,而最后一个节点则指向一个空值。
一个单向链表的节点被分成两个部分。
第一个部分保存或者显示关于节点的信息,第二个部分存储下一个节点的地址。
单向链表只可向一个方向遍历。
链表最基本的结构是在每个节点保存数据和到下一个节点的地址,在最后一个节点保存一个特殊的结束标记,另外在一个固定的位置保存指向第一个节点的指针,有的时候也会同时储存指向最后一个节点的指针。
一般查找一个节点的时候需要从第一个节点开始每次访问下一个节点,一直访问到需要的位置。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
重庆邮电大学
课程设计实验报告
班级:1301416
姓名:陈昊
学号:2014214156
指导老师:夏晨洋
课程名称:数据结构
实验时间:2015年10月26日-2015年11月2日实验地点:数字图书馆负一楼B132
实验二单链表的存储与操作
一、实验目的
1.理解线性表的逻辑结构;
2.理解单链表的存储结构特点,掌握单链表的存储分配要点;
3.掌握单链表的基本操作及实现,并能正确分析其时间复杂度。
二、主要数据结构描述
LinkList( ); //建立只有头结点的空链表
LinkList(T a[ ], int n); //建立有n个元素的单链表
~LinkList(); //析构函数
int Length(); //求单链表的长度
T Get(inti); //取单链表中第i个结点的元素值
int Locate(T x); //求单链表中值为x的元素序号
void Insert(inti, T x); //在单链表中第i个位置插入元素值为x的结点
T Delete(inti); //在单链表中删除第i个结点
void PrintList( ); //遍历单链表,按序号依次输出各元素
Node<T> *first; //单链表的头指针
在单链表中,需要有构造函数用来构造整个单链表。
需要析构函数来删除整个单链表。
需要一个Length函数来求单链表的长度。
需要一个取值函数Get,传入节点的编号,返回节点的值。
需要一个求序号的函数,传入数据的值,返回数据对应的编号,即在单链表中的位置。
需要一个插入函数,用来在特定的位置插入一个节点用来存储新数据。
需要一个删除函数,用来删除某个节点,并将该节点两端的节点连起来。
需要一个遍历函数,用以遍历单链表。
三、算法的基本思想描述
1. 按位置/值查找:按位置和按值查找的思路大体相同,需要一个工作指针来对整个链表进行遍历,如果所遇到的编号或值与想要的一致,便会把工作指针的信息返回。
此函数只需对链表遍历一次,所以平均时间复杂度为O(n);
2. 在位置i插入一个数据元素:此函数可以大体分成两个部分。
第一个部分是遍历,寻找到要插入的位置,这个与上面的方法相同。
第二个部分是插入,要先申
请一个新节点s,在让s的指针域等于前一个节点p的指针域,最后让p的指针域等于s。
此函数只需对链表遍历一次,所以平均时间复杂度为O(n);
3. 删除位置i的数据元素:删除函数也有两个部分,第一个与插入相同,第二个先要暂存被删节点,用以返回,再让前一个节点的指针域等于后一个节点,最后删除被删节点。
此函数只需对链表遍历一次,所以平均时间复杂度为O(n);
4. 初始化单链表(有参):有前插法和尾插法,实际上都是在链表的后面再添加一个新节点,所以时间复杂度为O(n);
5. 遍历单链表、求单链表长度、销毁单链表:这三个函数都是要遍历单链表,所以时间复杂度为O(n)。
四、运行的结果截图
五、实验体会和收获
通过这次试验,我熟悉了如何取单链表中第i个结点的元素值,如何按位查找位置为i的元素并输出值,如何构建一个单链表。
总之这次试验然我熟悉了很多单链表的操作。
六、程序清单。
LinkList.h
LinkList.cpp
LinkListMain.cpp。