单链表完整算法

合集下载

单链表查找插入删除算法时间效率分析

单链表查找插入删除算法时间效率分析

单链表查找插⼊删除算法时间效率分析单链表查找时间效率分析:
代码:
Lnode *LocateElem_L(LinkList L, ElemType e){
//在线性表L中查找值为 e 的数据元素
//找到,则返回 L 中值为 e 的数据元素的地址
//查找失败返回NULL
p=L->next;
while(p!=NULL && p->data!=e){
p=p->next;
}
return p;
}
上述代码中,循环体⾥的 p=p->next 执⾏多少次?或者说循环执⾏多少次,和我们要查找的元素 e 所在位置有关系如果单链表中第⼀个元素,或者说⾸元结点就是 e ,那么仅执⾏⼀次即可。

如果不是,则顺着指针链,依次向后查找。

因线性链表只能顺序存取,即在查找时要从头指针找起,查找的时间福再度为 O(n)。

插⼊和删除:
因线性链表在插⼊或删除时,不需要移动元素,只要修改指针,⼀般情况下时间复杂度为O(1)。

但是,如果要在单链表中进⾏前插或删除操作,由于要从头查找前驱结点,所耗时间复杂度为O(n)。

进⾏插⼊和删除的操作是常数即便,但是寻找前驱才要O(n)。

写出以单链表为存储结构的一组数据的简单选择排序算法。

写出以单链表为存储结构的一组数据的简单选择排序算法。

写出以单链表为存储结构的一组数据的简单选择排序算法。

以下是单链表存储结构的简单选择排序算法的实现:
```python
def selection_sort(link_list):
n = len(link_list)
for i in range(n):
min_idx = i
for j in range(i+1, n):
if link_list[j] < link_list[min_idx]:
min_idx = j
link_list[i], link_list[min_idx] = link_list[min_idx], link_list[i]
return link_list
```
算法的基本思路是,遍历待排序的链表,找到未排序部分中的最小值,然后将该值与链表的第一个元素交换位置,然后再遍历剩余的元素,继续按照此方法进行排序,直到整个链表都被排序。

在上面的实现中,我们通过 `min_idx` 变量来保存当前未排序部分中的最小值的索引。

在第一次遍历时,min_idx 等于 i,因为在未排序部分中,第一个元素通常是最小的。

在后续的遍历中,我们不断地寻找未排序部分中的最小值,并将其与链表的第一个元素交换位置,最后返回排好序的链表。

单链表的基本算法实验报告

单链表的基本算法实验报告

单链表的基本算法实验报告单链表的的基本算法学号:⽇期:⼀、需求分析1.程序的功能(1)程序具备任意选择删除、插⼊、查找数据元素,和求单链表表长等⼏项功能。

(2)当选择删除功能时,从键盘读⼊欲删除的元素位置,按指定位置删除;当选择插⼊功能时,从键盘读⼊新元素值和被插⼊位置,在指定位置插⼊;当选择查找功能时,从键盘读⼊欲查找的元素值,返回其位置序号;当选择求表长功能时,返回该单链表表长的数值。

2.输⼊输出的要求(1)从键盘读⼊⼀组整数,按输⼊顺序形成单链表。

(2)每种操作结束后,都能在屏幕上打印出此时单链表元素的遍历结果。

(3)测试数据从键盘输⼊⼀组若⼲数字使之形成单链表⼆、概要设计1.本程序所⽤的抽象数据类型的定义typedef struct{DataType items[LISTSIZE];int length;}SqList;2.主程序的流程及各程序模块之间的层次关系先定义⼀个顺序表,结构体⾥的⼀位数组为顺序表内容,然后调⽤int InitList(SqList *L)初始化顺序表,然后已键盘输⼊的形式输⼊⼀组⼀维数组,保存到顺序表⾥,次数组以-222作为结束符号,然后调⽤int TraverseList(SqList L)遍历次顺序表,在主函数⾥实⾏do-while在⾥⾯进⾏意选择删除、插⼊、查找数据元素的功能。

删除功能调⽤int ListInsertt(SqList *L),int ListInsertt(SqList *L)⼜调⽤int ListDelete(SqList *L),为嵌套调⽤。

插⼊功能调⽤int ListInsert(SqList *L,int pos,DataType item)此函数。

查找功能调⽤int Find(SqList L);在以上⼦函数中要⽤到int ListEmpty(SqList L)判空函数。

三、详细设计1.采⽤c 语⾔定义相关的数据类型(1)⽤C 语⾔描述的单链表的节点结构 typedef struct Node{DataType data;struct Node *next;}LNode, *PNode,*LinkList; 四、调试分析1.调试中遇到的问题及对问题的解决⽅法在调试过程在运⾏插⼊和查找功能时把位置找错,总是找到正确位置的后⼀个,后来经过仔细阅读课本发现我把书上定义理解错了。

数据结构与算法——单链表的实现及原理

数据结构与算法——单链表的实现及原理

数据结构与算法——单链表的实现及原理1. 单链表的原理 链表是线性表的链式存储⽅式,逻辑上相邻的数据在计算机内的存储位置不必须相邻,那么怎么表⽰逻辑上的相邻关系呢?可以给每个元素附加⼀个指针域,指向下⼀个元素的存储位置。

如图所⽰: 从图中可以看出,每个结点包含两个域:数据域和指针域,指针域存储下⼀个结点的地址,因此指针指向的类型也是结点类型链表的核⼼要素:Ø 每个节点由数据域和指针域组成 Ø 指针域指向下⼀个节点的内存地址。

1.1 结构体定义1 Typedef struct LinkNode2 {3 ElemType data; //节点中存放数据的类型4struct LinkNode* next; //节点中存放下⼀节点的指针5 }LinkList, LinkNode;2. 单链表初始化链表的节点均单向指向下⼀个节点,形成⼀条单向访问的数据链1//单链表的初始化2 typedef struct _LinkNode3 {4int data; //结点的数据域5struct _LinkNode* next; //结点的指针域6 }LinkNode, LinkList; //链表节点、链表78bool InitList(LinkList*& L) //构造⼀个空的单链表 L9 {10 L = new LinkNode; //⽣成新结点作为头结点,⽤头指针 L 指向头结点11if(!L)return false; //⽣成结点失败12 L->next=NULL; //头结点的指针域置空13return true;14 }3. 单链表增加元素 - 单链表前插法插⼊节点的要素就是要找到要插⼊位置的前⼀个节点,将这个节点的Next赋值给新节点,然后将新节点的地址赋值给前⼀个节点的Next便可,任意位置插⼊和前插法均是如此。

1//前插法2bool ListInsert_front(LinkList * &L, LinkNode * node) //参数1 链表指针参数2 要插⼊的节点元素3 {4if (!L || !node) return false; //如果列表或节点为空返回 false5 node->next = L->next; //将头节点指向节点1的地址赋值给要插⼊节点的指针域,使要插⼊的节点先与后部相连6 L->next = node; //将插⼊节点的地址赋值给头结点的指针域,使要插⼊节点与头结点相连78return true;9 }4. 单链表增加元素 - 单链表尾插法1//尾插法2bool ListInsert_back(LinkList*& L, LinkNode* node)3 {4 LinkNode* last = NULL; //创建空指针,5if (!L || !node) return false; //如果列表或节点为空返回 false67 last = L;8while (last->next) last = last->next; //使⽤ last 找到最后⼀个节点910 node->next = NULL; //要插⼊节点由于在尾部,指针域置为 NULL11 last->next = node; //将要插⼊节点的地址赋值给之前的尾部节点的指针域,将要插⼊节点放置到尾部12return true;13 }5. 单链表增加元素 - 单链表任意位置插⼊插⼊节点的要素就是要找到要插⼊位置的前⼀个节点,将这个节点的Next赋值给新节点,然后将新节点的地址赋值给前⼀个节点的Next便可,任意位置插⼊和前插法均是如此。

写一求单链表的结点数目listlength(l)的算法。

写一求单链表的结点数目listlength(l)的算法。

写一求单链表的结点数目listlength(l)的算法。

单链表是一种常见的数据结构,它由一系列结点组成,每个结点都有一个指向下一个结点的指针。

求单链表的结点数目listlength(l)是一个常见的问题,下面我们就来讨论一下如何求解这个问题。

首先,我们需要定义一个变量count,用来记录单链表的结点数目。

然后,我们从单链表的头结点开始遍历,每遍历一个结点,count就加1,直到遍历到最后一个结点,count的值就是单链表的结点数目。

具体的算法步骤如下:
(1)定义一个变量count,用来记录单链表的结点数目,初始值为0。

(2)从单链表的头结点开始遍历,每遍历一个结点,count就加1。

(3)直到遍历到最后一个结点,count的值就是单链表的结点数目。

(4)返回count的值。

上述就是求单链表的结点数目listlength(l)的算法,它的时间复杂度为O(n),空间复杂度为O(1),其中n为单链表的结点数目。

总之,求单链表的结点数目listlength(l)是一个常见的问题,上述算法可以有效地解决这个问题,它的时间复杂度和空间复杂度都很低,是一种非常有效的算法。

数据结构___头插法和尾插法建立链表(各分有无头结点)

数据结构___头插法和尾插法建立链表(各分有无头结点)

实验一链表的建立及基本操作方法实现一、【实验目的】1、理解和掌握单链表的类型定义方法和结点生成方法。

2、掌握利用头插法和尾插法建立单链表和显示单链表元素的算法。

3、掌握单链表的查找(按序号)算法。

4、掌握单链表的插入、删除算法。

二、【实验内容】1、利用头插法和尾插法建立一个无头结点单链表,并从屏幕显示单链表元素列表。

2、利用头插法和尾插法建立一个有头结点单链表,并从屏幕显示单链表元素列表。

3、将测试数据结果用截图的方式粘贴在程序代码后面。

重点和难点:尾插法和头插法建立单链表的区别。

建立带头结点和无头结点单链表的区别。

带头结点和无头结点单链表元素显示方法的区别三、【算法思想】1) 利用头插法和尾插法建立一个无头结点单链表链表无头结点,则在创建链表时,初始化链表指针L=NULL。

当用头插法插入元素时,首先要判断头指针是否为空,若为空,则直接将新结点赋给L,新结点next指向空,即L=p,p->next=NULL,若表中已经有元素了,则将新结点的next指向首结点,然后将新结点赋给L即(p->next=L,L=p)。

当用尾插法插入元素时,首先设置一个尾指针tailPointer以便随时指向最后一个结点,初始化tailPointer和头指针一样即tailPointer=L。

插入元素时,首先判断链表是否为空,若为空,则直接将新结点赋给L即L=p,若不为空,else将最后一个元素的next指向新结点即tailPointer->next=p,然后跳出这个if,else语句,将新结点next指向空,并且将tailPointer指向新结点即p->next=NULL,tailPointer=p。

2) 利用头插法和尾插法建立一个有头结点单链表链表有头结点,则在创建链表时,初始化链表指针L->next = NULL。

与无头结点区别在于,判断链表为空是根据L->next是否为空。

用头插法插入元素时,要判断链表是否为空,若为空则将新结点next指向空,作为表尾,若不为空,则直接插入,将新结点next指向头结点next的指向,再将头结点next指向新结点即p->next=L->next,L->next=p。

设计两个有序单链表的合并排序算法

设计两个有序单链表的合并排序算法

设计两个有序单链表的合并排序算法有序单链表的合并排序,是一种高效的排序算法,可以在较短的时间内对大量数据进行排序。

这种排序算法的核心在于将两个有序的单链表合并成一个有序的单链表,然后再对整个链表进行排序。

合并排序算法的基本原理是分治法。

将需要排序的数组不断地分解成两个子数组,直到每个子数组只包含一个元素为止。

然后再将这些子数组两两合并,直到整个数组被合并成一个有序的数组为止。

这里介绍两个有序单链表的合并排序算法,它们分别是迭代算法和递归算法。

1. 迭代算法迭代算法是一种通用的算法,它的思路是利用循环结构来重复执行一段相同或相似的代码,从而解决一类问题。

对于有序单链表的合并排序,迭代算法的基本思路是将两个有序单链表的元素依次比较,然后将较小的元素加入到新的链表中,直到两个链表中的元素全部被加入到新链表中为止。

以下是迭代算法的具体实现过程:```// 合并两个有序单链表Node* mergeList(Node* head1, Node* head2) { // 新建一个头结点Node* dummy = new Node(-1);// 定义两个指针,分别指向两个链表的头结点 Node* p = head1;Node* q = head2;// 定义一个指针,指向新链表的最后一个节点 Node* curr = dummy;// 循环比较两个链表中的元素while (p != nullptr && q != nullptr) {if (p->val <= q->val) {curr->next = p;p = p->next;} else {curr->next = q;q = q->next;}curr = curr->next;}// 将剩余的元素加入到新链表中curr->next = p != nullptr ? p : q;// 返回新链表的头结点return dummy->next;}// 归并排序Node* mergeSort(Node* head) {if (head == nullptr || head->next == nullptr) {return head;}// 定义两个指针,一个快指针每次走两步,一个慢指针每次走一步 Node* slow = head;Node* fast = head->next;while (fast != nullptr && fast->next != nullptr) {slow = slow->next;fast = fast->next->next;}// 将链表分成两部分Node* head1 = head;Node* head2 = slow->next;slow->next = nullptr;// 分别对两部分链表进行归并排序head1 = mergeSort(head1);head2 = mergeSort(head2);// 合并两个有序单链表return mergeList(head1, head2);}```2. 递归算法递归算法的思想是将一个大问题分解成若干个小问题,然后逐个解决这些小问题,最终得到大问题的解决方案。

数据结构实验报告实现单链表各种基本运算的算法

数据结构实验报告实现单链表各种基本运算的算法

实验截图(1)void InitList(LinkNode *&L)//初始化线性表{L=(LinkNode *)malloc(sizeof(LinkNode)); //创建头结点L->next=NULL;//单链表置为空表}void DestroyList(LinkNode *&L)//销毁线性表{LinkNode *pre=L,*p=pre->next;实验截图(2)bool GetElem(LinkNode *L,int i,ElemType &e) //求线性表中第i个元素值{ int j=0;if (i<=0) return false;//i错误返回假LinkNode *p=L;//p指向头结点,j置为0(即头结点的序号为0) while (j<i && p!=NULL)//找第i个结点p{ j++;p=p->next;}if (p==NULL)//存在值为e的结点,返回其逻辑序号ireturn(i);}实验截图(3)bool ListInsert(LinkNode *&L,int i,ElemType e) //插入第i个元素{ int j=0;if (i<=0) return false;//i错误返回假LinkNode *p=L,*s;//p指向头结点,j置为0(即头结点的序号为0) while (j<i-1 && p!=NULL)//查找第i-1个结点p{ j++;p=p->next;}}实验截图(4)编写exp2-2.cpp程序包含有关代码//文件名:exp2-2.cpp#include "linklist.cpp"int main(){LinkNode *h;ElemType e;printf("单链表的基本运算如下:\n");printf(" (1)初始化单链表h\n");InitList(h);printf(" (2)依次采用尾插法插入a,b,c,d,e元素\n");return 1;}实验截图(5)运行得到结果实验截图(6)。

pta单链表元素最大值以及结点数

pta单链表元素最大值以及结点数

主题:pta单链表元素最大值以及结点数一、简介pta是一个上线评测系统,专门用于评测程序设计能力。

在pta中,关于单链表的问题广泛存在,而求单链表中元素最大值以及结点数也是一种常见的问题。

二、绪论单链表是一种常见的数据结构,由一系列结点组成,每个结点包含数据域和指针域。

求单链表中元素的最大值以及结点数是对链表基本操作的考察,也是对算法思维和编程能力的考验。

三、元素最大值的求解1. 遍历法:最简单直接的方法是使用遍历法,从链表的头结点开始,一直遍历到尾部结点,记录下遍历过程中所遇到的最大值,即可得到单链表中元素的最大值。

该方法的时间复杂度为O(n),n为链表的长度。

2. 递归法:另一种方法是使用递归法,递归地比较每个结点的值,并更新最大值。

该方法也能够得到单链表中元素的最大值,但是相比于遍历法,递归法的实现可能会更加复杂,而且在链表长度过大时可能会导致栈溢出。

3. 思考:对于单链表中元素最大值的求解,还可以考虑是否可以借助其他数据结构,如堆或者优先队列,来实现更加高效的求解方法。

这需要对数据结构与算法进行综合考虑与分析。

四、结点数的求解1. 遍历法:同样可以使用遍历法来求解单链表的结点数,从链表的头结点开始,一直遍历到尾部结点,在遍历过程中记录下结点的个数即可。

该方法的时间复杂度同样为O(n)。

2. 递归法:类似地,也可以使用递归法来逐个遍历结点,并更新结点个数。

但是同样需要注意在链表长度过大时可能会出现栈溢出的情况。

3. 思考:对于单链表中结点数的求解,是否可以通过对链表的结构进行改造或者引入新的数据结构,来实现更加高效的求解方法也是值得思考的问题。

五、总结求解单链表中元素最大值以及结点数是一个基础的算法问题,也是对程序设计能力的考验。

在实际工作中,对于常用数据结构的基本操作,如单链表的遍历与求解问题,需要熟练运用常见的解题方法,同时也需要培养自己发现问题、分析问题和解决问题的能力。

六、参考资料1. 《算法导论》2. 《数据结构与算法分析》3. 《程序设计导论》七、致谢感谢各位老师和同学在我学习和工作中给予的帮助与支持,让我不断提高自己的算法与编程能力。

数据结构算法经典 -单链表

数据结构算法经典 -单链表
}break;
case 4:
{
printf("请输入要删除的结点: ");
scanf("%d",&g);
x4=delete(&head,g);
printf(x4);
display(&head);
void display(struct LNode **p);
main()
{
struct LNode *head,*q; /*定义静态变量*/
int select,x1,x2,x3,x4;
int i,n;
int m,g;
char e,y;
head=setnull(&head); /*建议链表并设置为空表*/
n++;
q=q->next;
}
return(n);
}
ElemType get(struct LNode **p,int i)
{
int j=1;
struct LNode *q=*p;
while (j<i&&q!=null)
{
q=q->next;
int length (struct LNode **p);
ElemType get(struct LNode **p,int i);
void insert(struct LNode **p,ElemType x,int i);
int delete(struct LNode **p,int i);
/*单链表的各种操作*/
# define null 0
typedef char ElemType; /* 字符型数据*/

循环单链表

循环单链表

第7讲循环单链表单链形式的循环链表结构是首尾相接的单链表,即最后一个结点的指针指向链表的表头结点或第一个结点。

判别当前结点p是否为循环单链表L的表尾结点的判别条件:p->next!=L,即p->next是否指回到头,与一般单链表p->next是否为NULL不同。

在循环单链表中,也可只设置一个头结点,这样,空循环链表仅由一个自成循环的头结点表示。

循环链表:定义:即首尾相接的链表。

结构:尾结点的指针域指向头结点或表的首元结点;循环链表示意图:L(a)带头结点的空循环链表(b)带头结点的循环单链表的一般形式循环单链表的合并算法:【算法思想】●遍历两链表找表尾;●将第一表尾链接第二表头,将第二表尾链接第一表头;【算法步骤】1.设置指针p,q从头遍历查找两链表的表尾;2.修改第一表的尾指针,使其指向第二表的头结点;3.修改第二表的尾指针,使其指向第一表的头结点;循环单链表的合并算法举例:有两个带头结点的循环单链表LA、LB,设计算法,将两个循环单链表合并为一个循环单链表,其头指针为LA。

【算法描述】LinkList merge_1(LinkList LA,LinkList LB){ /*此算法将两个采用头指针的循环单链表的首尾连接起来*/Node *p, *q;p=LA;q=LB;while (p->next!=LA) p=p->next; /*找到表LA的表尾,用p指向它*/ while (q->next!=LB) q=q->next; /*找到表LB的表尾,用q指向它*/ q->next=LA; /*修改表LB 的尾指针,使之指向表LA 的头结点*/p->next=LB->next; /*修改表LA的尾指针,使之指向表LB 中的第一个结点*/free(LB);return(LA);}采用上面的方法,需要遍历链表,找到表尾,其执行时间是O (n)。

实现单链表的各种基本运算的算法

实现单链表的各种基本运算的算法

实现单链表的各种基本运算的算法#include<iostream>using namespace std;#include<malloc.h>typedef char Elem;typedef struct AA{Elem data;struct AA *next;}A;void Create(A *&L){L=(A *)malloc(sizeof(A));L->next=NULL;}bool InsertList(A *&L,Elem e,int i){A *s,*p=L;int j=0;if(i<=0)return false;while(j<i-1&&p!=NULL){j++;p=p->next;}if(p==NULL)return false;else{s=(A *)malloc(sizeof(A));s->data=e;s->next=p->next;p->next=s;return true;}}void DisPlay(A *L){A *s=L->next;while(s!=NULL){cout<<s->data<<" ";s=s->next;}cout<<endl;}void DisPlayA(A *L){int i=0;A *p=L;while(p->next!=NULL){i++;p=p->next;}cout<<i<<endl;}void empty1(A *L){if(L->next==NULL)cout<<"The list is empty!"<<endl;elsecout<<"The list is not empty!"<<endl;}void DisPlayA(A *L,int i){int j=1;A *p=L->next;while(j<i){p=p->next;j++;}cout<<"The third element is "<<p->data<<"."<<endl; }void Location(A *L,Elem e){int i=1;A *p=L->next;while(p!=NULL&&p->data!=e){p=p->next;i++;}cout<<"The location of element 'a' is: "<<i<<endl; }void Del(A *&L,int i){A *p=L->next;int j=1;while(j<i-1&&p!=NULL){p=p->next;j++;}p->next=p->next->next;}void Des(A *&L){A *pre=L,*p=L->next;while(p!=NULL){free(pre);pre=p;p=p->next;}free(pre);}int main(){A *s1;Elem e;int i=0;Create(s1);for(int i=1;i<6;i++){cin>>e;InsertList(s1,e,i);}DisPlay(s1);empty1(s1);DisPlayA(s1,3);Location(s1,'a');InsertList(s1,'f',4);DisPlay(s1);Del(s1,3);DisPlay(s1);Des(s1);}。

数据结构 实验一:实现单链表各种基本运算的算法

数据结构 实验一:实现单链表各种基本运算的算法

- 1 -实验一:实现单链表各种基本运算的算法一、 实验目的1、 掌握单链表存储结构的类型定义;2、 实现单链表各种基本运算的算法。

二、 实验环境1、 Windows 操作系统;2、 Visual C++ 6.0三、 实验内容实现单链表各种基本运算的算法。

四、 概要设计1.存储结构的类型定义:Typedef struct LNode{ElemType data;Struct LNode *next;}LinkList;2.单链表示意图:3.项目组成图:4.algo2_2.cpp 的程序文件包含的函数原型及功能:InitList(LinkList *&L) 初始化单链表LDestroyList(LinkList *&L) 释放单链表LListEmpty(LinkList *L)判断单链表L 是否为空表ListLength(LinkList *L)返回单链表L 的元素个数DispList(LinkList *L)输出单链表LGetElem(LinkList *L,int i,ElemType &e)获取单链表L 的第i 个元素LocateElem(LinkList *L,ElemType e)在单链表L 中查找元素eListInsert(LinkList *&L,int i,ElemType e)在单链表L 中的第i 个位置上插入元素e…… head a 1 a 2 a 3 a n ∧ListDelete(LinkList *&L,int i,ElemType &e)在单链表L中删除第i个元素5.exp2_2.cpp程序文件简介:InitList(LinkList *&L) 初始化单链表LDestroyList(LinkList *&L) 释放单链表LListEmpty(LinkList *L) 判断单链表L是否为空表ListLength(LinkList *L) 返回单链表L的元素个数DispList(LinkList *L) 输出单链表LGetElem(LinkList *L,int i,ElemType &e) 获取单链表L的第i个元素LocateElem(LinkList *L,ElemType e) 在单链表L中查找元素eListInsert(LinkList *&L,int i,ElemType e) 在单链表L中的第i个位置上插入元素e ListDelete(LinkList *&L,int i,ElemType &e) 在单链表L中删除第i个元素6.proj2-2的项目的模块结构:在文件algo2-2中,(1)定义单链表结构类型;(2)初始化单链表(3)定义释放单链表的函数(4)定义判断单链表是否为空的函数(5)定义返回单链表元素个数的函数(6)定义输出单链表的函数(7)定义获取第i个元素的函数(8)定义查找元素的函数(9)定义插入元素的函数(10)定义删除元素的函数在文件exp2-2中分别调用algo2-2中所定义的函数7.函数调用关系图:五、详细设计源代码清单见附录。

单链表的基本运算

单链表的基本运算
{ Node *s; char c; int flag=1; while(flag) /* flag 初值为 1,当输入“$”时,置 flag 为 0,
建表结束*/ { c=getchar(); if(c!=’$’) { s=(Node*)malloc(sizeof(Node)); /*建立新结点 s*/ s->data=c; s->next=L->next; /*将 s 结点插入表头*/ L->next=s; } else flag=0;
3. 结果判断 如找到第 i 个结点,则返回结点 p;
如表查完未找到,则返回空。
【算法描述】
Node * Get (LinkList L, int i) / * 在带头结点的单链表 L 中查找第 i 个结点,若找到(1≤i≤n),则返回 该结点的存储位置; 否则返回 NULL * / { int j;
【算法描述】
int ListLength(LinkList L)
/*求带头结点的单链表 L 的长度*/
{ Node *p;
p=L->next;
j=0; /*用来存放单链表的长度*/
while(p!=NULL)
{
p=p->next;
j ++;
}
return j; /*j 为求得的单链表长度*/
} /* ListLength */
H

s r
(a)初始化的空表
C1 ∧
(b)申请新结点并赋值
s 指向新申请的结点空间;
s->data:=C1
H
c1 ∧
r
(c)插入第一个结点
s
① r->next=s;
c1 H

链表(单链表 双向循环)实验报告讲解

链表(单链表 双向循环)实验报告讲解

数据结构实验报告T1223-3-21余帅实验一实验题目:仅仅做链表部分难度从上到下1.双向链表,带表头,线性表常规操作。

2.循环表,带表头,线性表常规操作。

3.单链表,带表头,线性表常规操作。

实验目的:了解和掌握线性表的逻辑结构和链式存储结构,掌握单链表的基本算法及相关的时间性能分析。

实验要求:常规操作至少有:1.数据输入或建立2.遍历3.插入4.删除必须能多次反复运行实验主要步骤:1、分析、理解给出的示例程序。

2、调试程序,并设计输入数据,测试程序的如下功能:1.数据输入或建立2.遍历3.插入4.删除单链表示意图:headhead head 创建删除双向循环链表示意图:创建程序代码://单链表#include<iostream.h>#include<windows.h>const MAX=5;enum returninfo{success,fail,overflow,underflow,range_error}; int defaultdata[MAX]={11,22,33,44,55};class node{public:int data;node *next;};class linklist{private:node *headp;protected:int count;public:linklist();~linklist();bool empty();void clearlist();returninfo create(void);returninfo insert(int position,const int &item);returninfo remove(int position) ;returninfo traverse(void);};linklist::linklist(){headp = new node;headp->next = NULL;count=0;}linklist::~linklist(){clearlist();delete headp;}bool linklist::empty(){if(headp->next==NULL)return true;elsereturn false;}void linklist::clearlist(){node *searchp=headp->next,*followp=headp;while(searchp->next!=NULL){followp=searchp;searchp=searchp->next;delete followp;}headp->next = NULL;count = 0;}returninfo linklist::create(){node *searchp=headp,*newnodep;for(int i=0;i<MAX;i++){newnodep = new node;newnodep->data = defaultdata[i];newnodep->next = NULL;searchp->next = newnodep;searchp = searchp->next;count++;}searchp->next = NULL;traverse();return success;}returninfo linklist::insert(int position,const int &item) //插入一个结点{if(position<=0 || position>=count)return range_error;node *newnodep=new node,*searchp=headp->next,*followp=headp;for(int i=1; i<position && searchp!=NULL;i++){followp=searchp;searchp=searchp->next;}newnodep->data=item; //给数据赋值newnodep->next=followp->next; //注意此处的次序相关性followp->next=newnodep;count++; //计数器加一return success;}returninfo linklist::remove(int position) //删除一个结点{if(empty())return underflow;if(position<=0||position>=count+1)return range_error;node *searchp=headp->next,*followp=headp; //这里两个指针的初始值设计一前一后for(int i=1; i<position && searchp!=NULL;i++){followp=searchp;searchp=searchp->next;}followp->next=searchp->next; //删除结点的实际语句delete searchp; //释放该结点count--; //计数器减一return success;}returninfo linklist::traverse(void){node *searchp;if(empty())return underflow;searchp = headp->next;cout<<"连表中的数据为:"<<endl;while(searchp!=NULL){cout<<searchp->data<<" ";searchp = searchp->next;}cout<<endl;return success;}class interfacebase{public:linklist listface; //定义一个对象Cskillstudyonfacevoid clearscreen(void);void showmenu(void);void processmenu(void);};void interfacebase::clearscreen(void){system("cls");}void interfacebase::showmenu(void){cout<<"================================"<<endl;cout<<" 功能菜单 "<<endl;cout<<" 1.创建链表 "<<endl;cout<<" 2.增加结点 "<<endl;cout<<" 3.删除结点 "<<endl;cout<<" 4.遍历链表 "<<endl;cout<<" 0.结束程序 "<<endl;cout<<"======================================"<<endl;cout<<"请输入您的选择:";}void interfacebase::processmenu(void){int returnvalue,item,position;char menuchoice;cin >>menuchoice;switch(menuchoice) //根据用户的选择进行相应的操作{case '1':returnvalue=listface.create();if(returnvalue==success)cout<<"链表创建已完成"<<endl;break;case '2':cout<<"请输入插入位置:"<<endl;cin>>position;cout<<"请输入插入数据:"<<endl;cin>>item;returnvalue = listface.insert(position,item);if(returnvalue==range_error)cout<<"数据个数超出范围"<<endl;elsecout<<"操作成功!!!"<<endl;break;case '3':cout<<"输入你要删除的位置:"<<endl;cin>>position;returnvalue = listface.remove(position);if(returnvalue==underflow)cout<<"链表已空"<<endl;else if(returnvalue==range_error)cout<<"删除的数据位置超区范围"<<endl;elsecout<<"操作成功!!!"<<endl;break;case '4':listface.traverse();break;case '0':cout<<endl<<endl<<"您已经成功退出本系统,欢迎再次使用!!!"<<endl;system("pause");exit(1);default:cout<<"对不起,您输入的功能编号有错!请重新输入!!!"<<endl;break;}}void main(){interfacebase interfacenow;linklist listnow;system("color f0");interfacenow.clearscreen();while(1){interfacenow.showmenu();interfacenow.processmenu();system("pause");interfacenow.clearscreen();}}/* 功能:用双向循环链表存储数据1.创建链表2.增加结点3.删除结点4.遍历链表制作人:余帅内容:239行*/#include<iostream.h>#include<windows.h>const MAX=5;enum returninfo{success,fail,overflow,underflow,range_error}; int defaultdata[MAX]={11,22,33,44,55};class node{public:int data;node * next; //指向后续节点node * pre; //指向前面的节点};class linklist{private:node *headp;protected:int count;public:linklist();~linklist();bool empty();void clearlist();returninfo create(void);returninfo insert(int position,const int &item);returninfo remove(int position) ;returninfo traverse(void);};linklist::linklist(){headp = new node;headp->next = NULL;headp->pre = NULL;count=0;}linklist::~linklist(){clearlist();delete headp;}bool linklist::empty(){if(headp->next==NULL)return true;elsereturn false;}void linklist::clearlist(){node *searchp=headp->next,*followp=headp;while(searchp->next!=NULL){followp=searchp;searchp=searchp->next;delete followp;}headp->next = NULL;headp->pre = NULL;count = 0;}returninfo linklist::create(){node *searchp=headp,*newnodep;for(int i=0;i<MAX;i++){newnodep = new node;newnodep->data = defaultdata[i];newnodep->next = NULL;searchp->next = newnodep;newnodep->pre = searchp;searchp = searchp->next;count++;}searchp->next = headp;headp->pre = searchp;traverse();return success;}returninfo linklist::insert(int position,const int &item) //插入一个结点{if(position<=0 || position>count+1)return range_error;node *newnodep=new node;node *searchp=headp->next,*followp=headp;for(int i=1; i<position && searchp!=NULL;i++){followp=searchp;searchp=searchp->next;}newnodep->data=item; //给数据赋值newnodep->next = searchp;searchp->pre = newnodep;followp->next = newnodep;newnodep->pre = followp;count++; //计数器加一return success;}returninfo linklist::remove(int position) //删除一个结点{if(empty())return underflow;if(position<=0||position>=count+1)return range_error;node *searchp=headp->next,*followp=headp; //这里两个指针的初始值设计一前一后for(int i=1; i<position && searchp!=NULL;i++){followp=searchp;searchp=searchp->next;}followp->next=searchp->next; //删除结点的实际语句searchp->next->pre = followp;delete searchp; //释放该结点count--; //计数器减一return success;}returninfo linklist::traverse(void){node *searchp1,*searchp2;if(empty())return underflow;searchp1 = headp;searchp2 = headp;cout<<"连表中的数据为:"<<endl;cout<<"从左至右读取:";while (searchp1->next!=headp ) {searchp1 = searchp1 ->next;cout << searchp1->data<<" ";}cout<<endl;cout<<"从右至左读取:";while (searchp2->pre!=headp ) {searchp2 = searchp2 ->pre;cout << searchp2->data<<" ";}cout<<endl;return success;}class interfacebase{public:linklist listface; //定义一个对象Cskillstudyonface void clearscreen(void);void showmenu(void);void processmenu(void);};void interfacebase::clearscreen(void){system("cls");}void interfacebase::showmenu(void){cout<<"================================"<<endl;cout<<" 功能菜单 "<<endl;cout<<" 1.创建链表 "<<endl;cout<<" 2.增加结点 "<<endl;cout<<" 3.删除结点 "<<endl;cout<<" 4.遍历链表 "<<endl;cout<<" 0.结束程序 "<<endl;cout<<"======================================"<<endl;cout<<"请输入您的选择:";}void interfacebase::processmenu(void){int returnvalue,item,position;char menuchoice;cin >>menuchoice;switch(menuchoice) //根据用户的选择进行相应的操作{case '1':returnvalue=listface.create();if(returnvalue==success)cout<<"链表创建已完成"<<endl;break;case '2':cout<<"请输入插入位置:"<<endl;cin>>position;cout<<"请输入插入数据:"<<endl;cin>>item;returnvalue = listface.insert(position,item);if(returnvalue==range_error)cout<<"数据个数超出范围"<<endl;elsecout<<"操作成功!!!"<<endl;break;case '3':cout<<"输入你要删除的位置:"<<endl;cin>>position;returnvalue = listface.remove(position);if(returnvalue==underflow)cout<<"链表已空"<<endl;else if(returnvalue==range_error)cout<<"删除的数据位置超区范围"<<endl;elsecout<<"操作成功!!!"<<endl;break;case '4':listface.traverse();break;case '0':cout<<endl<<endl<<"您已经成功退出本系统,欢迎再次使用!!!"<<endl;system("pause");exit(1);default:cout<<"对不起,您输入的功能编号有错!请重新输入!!!"<<endl;break;}}void main(){interfacebase interfacenow;linklist listnow;system("color f0");interfacenow.clearscreen();while(1){interfacenow.showmenu();interfacenow.processmenu();system("pause");interfacenow.clearscreen();}}运行结果:1.创建链表:2.增加结点3.删除结点心得体会:本次实验使我们对链表的实质了解更加明确了,对链表的一些基本操作也更加熟练了。

设计一个算法求一个单链表中的结点...

设计一个算法求一个单链表中的结点...

第 1 章绪论1.1什么是数据结构?【答】:数据结构是指按一定的逻辑结构组成的一批数据,使用某种存储结构将这批数据存储于计算机中,并在这些数据上定义了一个运算集合。

1.2 数据结构涉及哪几个方面?【答】:数据结构涉及三个方面的内容,即数据的逻辑结构、数据的存储结构和数据的运算集合。

1.3 两个数据结构的逻辑结构和存储结构都相同,但是它们的运算集合中有一个运算的定义不一样,它们是否可以认作是同一个数据结构?为什么?【答】:不能,运算集合是数据结构的重要组成部分,不同的运算集合所确定的数据结构是不一样的,例如,栈与队列它们的逻辑结构与存储结构可以相同,但由于它们的运算集合不一样,所以它们是两种不同的数据结构。

1.4 线性结构的特点是什么?非线性结构的特点是什么?【答】:线性结构元素之间的关系是一对一的,在线性结构中只有一个开始结点和一个终端结点,其他的每一个结点有且仅有一个前驱和一个后继结点。

而非线性结构则没有这个特点,元素之间的关系可以是一对多的或多对多的。

1.5 数据结构的存储方式有哪几种?【答】:数据结构的存储方式有顺序存储、链式存储、散列存储和索引存储等四种方式。

1.6 算法有哪些特点?它和程序的主要区别是什么?【答】:算法具有(1)有穷性(2)确定性(3)0个或多个输入(4)1个或多个输出(5)可行性等特征。

程序是算法的一种描述方式,通过程序可以在计算机上实现算法。

1.7 抽象数据类型的是什么?它有什么特点?【答】:抽象数据类型是数据类型的进一步抽象,是大家熟知的基本数据类型的延伸和发展。

抽象数据类型是与表示无关的数据类型,是一个数据模型及定义在该模型上的一组运算。

对一个抽象数据类型进行定义时,必须给出它的名字及各运算的运算符名,即函数名,并且规定这些函数的参数性质。

一旦定义了一个抽象数据类型及具体实现,程序设计中就可以像使用基本数据类型那样,十分方便地使用抽象数据类型。

抽象数据类型的设计者根据这些描述给出操作的具体实现,抽象数据类型的使用者依据这些描述使用抽象数据类型。

单链表-按值查找

单链表-按值查找

单链表-按值查找按值查找有两种情况:①根据指定数据获取该数据所在位置(该数据的地址)②根据指定数据获取该数据所在的位置序号(是第⼏个数据元素)例:根据指定数据获取该数据所在的位置(地址)分别查找值为30和值为15的元素①⽤变量 e 表⽰要查找的元素⽤指针p 指向⾸元结点:p=L->next;②⽐较指针p 当前指向结点的数据域,与 e 是否相等③如果不等,则计数器加⼀,然后指针p 向右移动:p=p->next;然后⽐较新指向结点的数据域是否与 e 相等④找到后,如果要找的是第⼏个元素,返回 i 的值;如果要找的是位置,就返回指针p 的值。

⑤但如果查找⼀个并不存在的元素,当 p=NULL 时,就查找结束。

算法步骤:①从第⼀个结点(⾸元结点)起,依次和 e 相⽐较;②如果找到⼀个其值与 e 相等的数据元素,则返回其在链表中的 “位置” 或地址;③如果查遍整个链表都没有找到其值和 e 相等的元素,则返回 0 或 “NULL”。

代码://返回被查找元素内存地址的查找⽅法Lnode *LocateElem_L(LinkList L, Elemtype e){//在线性表L中查找为e的数据元素//找到,则返回L中值为e的数据元素的地址,查找失败返回NULLp=L->next;//循环条件:指针p 不为NULL,指针p所指向结点的data域不等于 ewhile(p && p->data!=e){p=p->next;//如果找到了,就返回结点存储地址,如果没找到就返回NULLreturn p;}}//根据指定数据获取该数据位置序号(第⼏个)int LocateElem_L(LinkList L, Elemtype e){p=L->next;j=1;while(p && p->data!=e){p=p->next;j++;}//返回 L 中值为 e 的数据元素的位置序号,查找失败返回0if(p){//如果找到了,也就是p不为NULL,就返回 L 中值为 e 的数据元素的位置序号return j;}else{//如果没找到,也就是p为NULL,就返回0return0;}}。

顺序表与单链表基本运算算法

顺序表与单链表基本运算算法

顺序表的基本运算实现假设表中数据元素的值为整数;#define MAX 100 //定义表最大长度容量,实际用不到那么多//顺序表结构定义typedef struct{int data[MAX]; //存放表结点int length; //当前表长度} SeqList;//创建初始顺序表SeqList *createList(int size){int i;SeqList *list;list=(SeqList *)malloc(sizeof(SeqList)); //分配空间printf("请输入顺序表中的整数,元素个数为%d\n",size);for(i=0;i<size;i++)scanf("%d",&list->data[i]) ; //逐一向顺序表中输入元素 list->length=size; //顺序表的长度赋值return list;}//打印顺序表中的现有元素printList(SeqList *list){int i;printf("\n目前顺序表中有%d个元素\n", list->length);printf("这些元素分别是:\n");for(i=0;i<list->length;i++)printf("%d ",list->data[i]); //依次打印输出顺序表中的元素printf("\n");}//在顺序表中查找值为e的元素,并返回它在表中的位置Int locate(SeqList *list, int e){int i=0;while(i<list->length && list->data[i]!=e)i++ ; //依次比较顺序表中各个元素if(i<list->length) return i+1; //找到元素的处理else printf("找不到元素!\n",); //未找到元素的处理}//在表中第i个元素之前插入新元素einsert(SeqList *list, int i , int e){int j;if (i<1 || i>list->length+1 ) //检查插入位置的合法性printf("插入位置非法!不能插入\n!");else if (list->length==MAX)printf("表满,不能插入!\n"); //检查表空满情况 else {for(j=list->length-1;j>=i-1;j--)list->data[j+1]=list->data[j];//从第n个元素开始到第i个元素依次向后移动一个位置 list->data[i-1]=e; //新元素e插入i位置list->length++; //表长加1}}//删除表中第i个元素delete(SeqList *list, int i){int j;if (i<1 || i>list->length ) printf("删除位置非法!不能删除!\n");//检查删除位置的合法性else if (list->length==0) printf("表空,不能删除!\n");//检查表空满情况else{for(j=i;j<=list->length;j++)list->data[j-1]=list->data[j];//从第i个元素开始到第n个元素依次向前移动一个位置 list->length--; //表长减1}}单链表的基本运算实现以下算法都是带头结点的算法;假设表中数据元素的值为整数;//链表结点结构定义typedef struct node{int data; //存放表结点值struct node *next; //存放表结点的直接后驱元素的地址} ListNode,*LinkList;//头插法创建初始链表LinkList create_h(int size){LinkList head,p;int i;head=(LinkList)malloc(sizeof(ListNode));//申请头结点的存储空间 head->next=Null;//头结点的next域为Nullprintf("请输入这%d个元素的值:\n",size);for(i=0;i<size;i++) //将新增结点插入头结点之后{p=(LinkList)malloc(sizeof(ListNode));scanf("%d",&p->data);p->next=head->next;head->next=p;}return head;}//尾插法创建初始链表LinkList create_t(int size){LinkList head,p,r;int i;head=(LinkList)malloc(sizeof(ListNode)); //申请头结点的存储空间 head->next=Null; //头结点的next域为Nullr=head;//尾指针指向头结点printf("请输入这%d个元素的值:\n",size);for(i=0;i<size;i++) //将新增结点插入到表尾{p=(LinkList)malloc(sizeof(ListNode));scanf("%d",&p->data);p->next=Null;r->next=p;r=p;//尾指针指向新增结点} return head; }//求链表的长度int length(LinkList head){LinkList p;int i;p=head->next;//工作指针指向表中第一个结点i=0;//计数器置0while(p!=Null){i++;//计数器计数p=p->next;//工作指针后移到下一个结点}return i;}//打印链表中的现有元素printList(LinkList head){LinkList p;p=head->next;//工作指针指向表中第一个结点while(p!=Null){printf("%d ",p->data);//打印当前指针所指结点的值p=p->next;//工作指针后移到下一个结点}}//按位查找元素DataType get(LinkList head ,int i){LinkList p;int j;p=head->next; //工作指针指向表中第一个结点j=1; //计数器置1while(p!=Null && j<i)//定位第i个结点{p=p->next;j++;}if(p!=Null && j==i) return p->data;//查找成功,p指向第i个结点,返回第i个结点值else return Null;//i值非法,查找失败}//按值查找元素LinkList locate(LinkList head,int x){LinkList p;p=head->next;while(p!=Null && p->data!=x)p=p->next;if (p!=Null && p->data==x){printf("找到该元素!”);return p;}else{printf("找不到该元素!\n");return Null;}}//在链表中第i个元素前插入新元素insert(LinkList head,int i,int x){LinkList p,s;int j;p=head;//工作指针指向头结点,方便在第1个结点之前插入新元素j=0;//计数器置0while(p!=Null && j<i-1)//将p指针定位到第i个结点的直接前驱接点上{p=p->next;j++;}if (p!=Null && j==i-1)//定位成功{s=(LinkList)malloc(sizeof(ListNode));//申请新结点存储空间s->data=x;s->next=p->next;//新结点插入p->next=s;//新结点插入}Else//插入位置非法printf("插入位置非法!\n");}//在链表中删除第i个结点元素delete(LinkList head,int i){LinkList p,q;int j;p=head; //工作指针指向头结点j=0; //计数器置0while(p->next!=Null && j<i-1)//将p指针定位到第i个结点的直接前驱接点上;{p=p->next;j++;}if(p->next!=Null && j==i-1){q=p->next;//q指向要被删除的结点p->next=q->next;//删除结点free(q);//释放已被删除结点的存储空间}elseprintf("空表或删除位置不合法!\n"); }。

单链表逆序算法

单链表逆序算法

下面来看一下很经典的“单链表逆序”问题。

很多公司的面试题库中都有这道题,有的公司明确题目要求不能使用额外的节点存储空间,有的没有明确说明,但是如果面试者使用了额外的节点存储空间做中转,会得到一个比较低的分数。

如何在不使用额外存储节点的情况下使一个单链表的所有节点逆序?我们先用迭代循环的思想来分析这个问题,链表的初始状态如图(1)所示:图(1)初始状态初始状态,prev是NULL,head指向当前的头节点A,next指向A节点的下一个节点B。

首先从A节点开始逆序,将A节点的next指针指向prev,因为prev 的当前值是NULL,所以A节点就从链表中脱离出来了,然后移动head和next 指针,使它们分别指向B节点和B的下一个节点C(因为当前的next已经指向B节点了,因此修改A节点的next指针不会导致链表丢失)。

逆向节点A之后,链表的状态如图(2)所示:图(2)经过第一次迭代后的状态从图(1)的初始状态到图(2)状态共做了四个操作,这四个操作的伪代码如下:head->next = prev;prev = head;head = next;next = head->next;这四行伪代码就是循环算法的迭代体了,现在用这个迭代体对图(2)的状态再进行一轮迭代,就得到了图(3)的状态:图(3)经过第二次迭代后的状态那么循环终止条件呢?现在对图(3)的状态再迭代一次得到图(4)的状态:图(4)经过第三次迭代后的状态此时可以看出,在图(4)的基础上再进行一次迭代就可以完成链表的逆序,因此循环迭代的终止条件就是当前的head指针是NULL。

现在来总结一下,循环的初始条件是:prev = NULL;循环迭代体是:next = head->next;head->next = prev;prev = head;head = next;循环终止条件是:head == NULL根据以上分析结果,逆序单链表的循环算法如下所示:61 LINK_NODE *ReverseLink(LINK_NODE *head)62{63 LINK_NODE *next;64 LINK_NODE *prev = NULL;6566while(head != NULL)67{68 next = head->next;69 head->next = prev;70 prev = head;71 head = next;72}7374return prev;75}现在,我们用递归的思想来分析这个问题。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

// 包含头文件#include <stdio.h>#include <malloc.h>#include <stdlib.h>// 为结点数据类型和结构体类型起别名typedefint datatype;typedefstructLinkNode{datatype data; // 数据域structLinkNode *next; // 指针域存放下一个结点的地址}LNode,*LinkList;LinkList L; // 单链表的头指针// 1.用头插法创建单链表LinkListCreateListHead(int n){// 创建头结点LNode *L = (LNode *)malloc(sizeof(LNode));L->next = NULL; // 设置指针域为空LinkList p; // p指向新结点for(inti=n;i>0;i--) // 先插入最后一个结点,插入次序与逻辑次序相反{// 生成新结点p = (LNode *)malloc(sizeof(LNode));// 从键盘输入新结点的值printf("请输入要插入第%d结点的值:\n",i);scanf("%d", &p->data);p->next = L->next; // 让L原来的后继结点成为p的后继结点L->next = p; // p成为L新的后继结点}return L; // 返回单链表的头指针}// 2.用尾插法创建单链表LinkListCreateListTail(int n){// 生成头结点L = (LNode *)malloc(sizeof(LNode));L->next = NULL;// 设置指针域为空// p指向新结点,q指向尾结点LinkList p, q = L;// 依次在末尾插入n个结点for(inti=1;i<=n;i++){// 生成新结点pp = (LNode *)malloc(sizeof(LNode));// 从键盘输入新结点的值printf("请输入第%d个结点的值:\n", i);scanf("%d",&p->data);p ->next = NULL; // 新结点(也是尾结点)的指针域为空// 把新结点链接到单链表的末尾q->next = p;// 让q指向新的尾结点q = p;}return L;// 返回单链表的头指针}// 3.显示单链表中的元素值voidShowList(LinkList L){if(L == NULL || L->next==NULL){printf("单链表为空。

\n");return;}LinkList p = L; // 指针p首先指向头结点while(p->next!=NULL) // 当指针p没有到达尾结点时{p = p->next; // 指针后移一个结点printf("%d\n",p->data); // 输出结点数据域的值}}// 4.求单链表的长度(结点的个数)intGetLength (LinkList L){LNode *p=L; /*p 先指向头结点*/int n=0; //n代表除头结点外的结点个数while(p->next != NULL){// 当指针p没有到达尾结点时p=p->next; //指针后挪一个结点n++; //结点个数+1}return n; //返回结点的个数}// 5.按序号查找:在单链表中查找第i个结点LinkListLocateElemByIndex(LinkList L, inti){LinkList p = L; // 指针p先指向头结点,负责后移int j = 0; // j用来计算到达结点的序号if(L==NULL || L->next==NULL) {printf("单链表为空。

\n");return NULL;}// p指针后移的条件:p不是尾结点,而且j<iwhile(p->next!=NULL && j<i){p = p->next; // p指针后移j++; // j递增}if(j==i) // 找到第i个结点时:j==i{return p; // 返回第i个结点的地址}else{return NULL; // 第i个结点不存在,返回NULL }}// 6.按值查找:在单链表中查找值为e的结点LinkListLocateElemByData(LinkList L, datatype e){LinkList p = L; //指针p先指向头结点,负责后移if(L==NULL || L->next==NULL) {printf("单链表为空。

\n");return NULL;}// p指针后移的条件:p不是尾结点,而且p->data!=e while(p->next!=NULL && p->data!=e){p = p->next; // p指针后移}// 找到值为e的结点if(p->data == e){return p; // 返回结点的地址}else{return NULL; // 结点不存在,返回NULL }}// 7.在单链表的第i个位置插入值为e的结点(在第i-1个结点后面插入新结点)voidInsertByIndex(LinkList L, inti, datatype e){LNode *s;LNode *p = LocateElemByIndex(L,i-1);//找到了第i-1个结点if(p!=NULL) {s=(LNode *)malloc(sizeof(LNode));s->data=e;// 修改指针域的两行代码次序不能颠倒s->next=p->next;p->next=s;printf("插入结点完成。

\n");}else {printf("单链表为空或插入位置有误。

\n");}}// 8.在单链表中值为e的结点之后插入新结点voidInsertByDataBehind(LinkList L, datatype e){LNode *s; // s指向新结点,p指向值为e的结点LNode *p = LocateElemByData(L,e);// 找到值为e的结点if(p!=NULL){// 在值为e的结点之后插入新结点s=(LNode *)malloc(sizeof(LNode));// 从键盘输入新结点的值printf("请从键盘输入新结点的值:\n");scanf("%d",&s->data);// 修改指针域的两行代码次序不能颠倒s->next = p->next;p->next = s;printf("插入结点完成。

\n");}else{printf("单链表为空或插入位置有误。

\n");}}// 9.在值为e的结点之前插入voidInsertByDataBefore(LinkListL,datatype e) {LinkList p=L,q,s;while(p->next !=NULL && p->data !=e){q = p;p = p->next;}if(p->data==e){s = (LinkList)malloc(sizeof(LNode));printf("请输入新结点的值:");scanf("%d",&s->data);s->next = p; //s->next=q->next;q->next = s;printf("插入完成。

\n");}else {printf("插入失败。

\n");}}// 10.在单链表中删除第i个结点voidDeleteByIndex(LinkList L, inti){LNode *p = LocateElemByIndex(L,i-1); // p指向第i-1个结点LNode *q = p->next; // q指向第i个结点(待删除结点)if (q!=NULL){p->next = q->next;free(q);}else{printf("单链表为空或删除位置有误。

\n");}}// 11.删除值为e的结点voidDeleteByData(LinkList L, datatype e) {LNode *p=L,*q; //p指向值为e的结点while(p->next!=NULL && p->data!=e) {q=p; //q指向p的前驱结点p=p->next;}if (p->data==e) {q->next = p->next;free (p);printf("删除成功。

\n");} else {printf("删除失败。

\n");}}// 12 删除值为e结点的后继结点voidDeleteByDataBehind(LinkList L, datatype e){LinkList p = L; //指针p先指向头结点,负责后移// p指针后移的条件:p不是尾结点,而且p->data!=e while(p->next!=NULL && p->data!=e){p = p->next; // p指针后移}LNode *q = p->next; // q指向p的后继结点(待删除结点)if (q!=NULL){p->next = q->next;free(q);}else{printf("单链表为空或值为e结点不存在。

\n");}}//主函数void main(){printf("----------------------------------\n");printf("| 1 头插法创建单链表|\n");printf("| 2 尾插法创建单链表|\n");printf("| 3 求单链表长度|\n");printf("| 4 显示单链表中的元素|\n");printf("| 5 查找第i个结点|\n");printf("| 6 查找值为e的结点|\n");printf("| 7 在第i个位置插入|\n");printf("| 8 在值为e结点之后插入|\n");printf("| 9 在值为e结点之前插入|\n"); printf("| 10 删除第i个结点|\n"); printf("| 11 删除值为e的结点|\n"); printf("| 12 删除值为e结点的后继结点|\n"); printf("| 0 退出|\n"); printf("----------------------------------\n");intnum; //选择操作对应的数字int count; //要插入元素的个数int length; //单链表的长度LinkList p; //存放查找结点的首地址inti; //要查找元素的序号datatype e; //要查找元素的值do {printf("请输入要选择操作对应的数字:");scanf("%d", &num);switch(num) {case 1://头插法创建单链表printf("请输入要插入结点的个数:");scanf("%d",&count);L = CreateListHead(count);if (L==NULL){printf("头插法创建失败。

相关文档
最新文档