不带头结点的单向链表的基本操作概论

合集下载

C实现头插法和尾插法来构建单链表(不带头结点)

C实现头插法和尾插法来构建单链表(不带头结点)

C实现头插法和尾插法来构建单链表(不带头结点)链表的构建事实上也就是不断插⼊节点的过程。

⽽节点的插⼊能够分为头插法和尾插法。

//// main.c// HeadInsertAndTailInsert//// Created by chenyufeng on 16/2/25.// Copyright © 2016年 chenyufengweb. All rights reserved.///*** 分别使⽤头插法和尾插法建⽴单链表*/#include <stdio.h>#include "stdlib.h"#include "string.h"typedef int elemType;//构造节点typedef struct ListNode{int element;struct ListNode *next;}Node;//初始化链表void initList(Node *pNode){pNode = NULL;printf("%s函数运⾏,头结点初始化完毕\n",__FUNCTION__);}//打印链表void printList(Node *pNode){if (pNode == NULL) {printf("%s函数运⾏,链表为空,打印失败\n",__FUNCTION__);}else{while (pNode != NULL) {printf("%d ",pNode->element);pNode = pNode->next;}printf("\n");}}//头插法Node *HeadInsert(Node *pNode){Node *pInsert;pInsert = (Node*)malloc(sizeof(Node));if (pInsert == NULL) {printf("%s函数运⾏。

不带头结点的循环单链表的初始化

不带头结点的循环单链表的初始化

不带头结点的循环单链表的初始化在数据结构中,循环单链表是一种非常常见的数据结构。

它与普通的单链表相似,区别在于循环单链表的尾结点指针不为空,而是指向头结点。

从而形成了一个闭环。

循环单链表在实际开发中有着广泛的应用,比如约瑟夫问题、舞蹈链等算法都是基于循环单链表实现的。

循环单链表的初始化是操作中的一个重要步骤。

不带头结点的循环单链表与带头结点的初始化稍有不同,但同样需要注意一些细节。

在这篇文章中,我们将深入探讨不带头结点的循环单链表的初始化过程,以及一些相关的知识点。

一、不带头结点的循环单链表的初始化在不带头结点的循环单链表中,我们需要特别注意链表为空的情况。

因为没有头结点,所以需要对第一个节点进行特殊处理。

在初始化过程中,我们需要将第一个节点指向自己,形成一个闭环。

代码实现如下:```C++typedef struct Node {int data;struct Node* next;} Node;void InitList(Node*& L) {L = (Node*)malloc(sizeof(Node));if (L == NULL) {// 内存分配失败处理exit(0);}L->next = NULL; // 头节点初始化为空}```以上代码中,我们使用了C++的结构体来定义循环单链表的节点。

在进行初始化时,我们为头结点分配内存,并将其next指针指向NULL,表示链表为空。

二、注意事项在不带头结点的循环单链表中,我们需要特别注意以下几点:1. 空链表的处理:在初始化过程中,需要将第一个节点指向自己,形成一个闭环。

这样链表为空时,也能正常进行插入、删除等操作。

2. 头节点的处理:由于没有头结点,插入和删除操作时需要特别处理第一个节点。

3. 遍历链表:由于没有头结点,遍历链表时需要单独考虑第一个节点。

以上是不带头结点的循环单链表初始化的一些注意事项,在实际应用中需要特别留意这些细节,避免出现错误。

不带头结点的链栈的基本操作

不带头结点的链栈的基本操作

不带头结点的链栈的基本操作链栈是一种常见的数据结构,它具有后进先出(LIFO)的特点,类似于现实生活中的栈。

链栈的实现方式有多种,其中一种是不带头结点的链栈。

本文将介绍不带头结点的链栈的基本操作,包括初始化、入栈、出栈、获取栈顶元素以及判断栈是否为空。

1. 初始化链栈初始化链栈时,需要创建一个空的链表。

可以通过定义一个指向链表头结点的指针来实现。

初始状态下,该指针为空,表示链栈为空。

2. 入栈操作入栈操作是将一个元素插入到链栈的栈顶。

首先需要创建一个新的结点,将要入栈的元素存储在该结点中。

然后,将新结点插入到链栈的栈顶,并更新链栈的指针。

具体步骤如下:- 创建一个新的结点,并将要入栈的元素存储在该结点中。

- 将新结点的指针指向链栈的栈顶元素。

- 更新链栈的指针,使其指向新的栈顶元素。

3. 出栈操作出栈操作是将链栈的栈顶元素删除,并返回该元素的值。

首先需要判断链栈是否为空,如果为空则无法进行出栈操作。

如果链栈不为空,则将栈顶元素删除,并更新链栈的指针。

具体步骤如下:- 判断链栈是否为空,如果为空则无法进行出栈操作,返回错误信息。

- 如果链栈不为空,则将链栈的栈顶元素保存到一个临时变量中。

- 更新链栈的指针,使其指向下一个栈顶元素。

- 返回保存的栈顶元素的值。

4. 获取栈顶元素获取栈顶元素操作是返回链栈的栈顶元素的值,而不删除该元素。

首先需要判断链栈是否为空,如果为空则无法获取栈顶元素。

如果链栈不为空,则返回链栈的栈顶元素的值。

具体步骤如下:- 判断链栈是否为空,如果为空则无法获取栈顶元素,返回错误信息。

- 如果链栈不为空,则返回链栈的栈顶元素的值。

5. 判断栈是否为空判断栈是否为空操作是检查链栈是否为空,即链栈中是否存在元素。

首先需要判断链栈的指针是否为空,如果为空则链栈为空,否则链栈不为空。

具体步骤如下:- 判断链栈的指针是否为空,如果为空则链栈为空,返回真;否则链栈不为空,返回假。

通过以上的基本操作,可以实现不带头结点的链栈的各种功能。

不带头结点的链栈的基本操作

不带头结点的链栈的基本操作

不带头结点的链栈的基本操作不带头结点的链栈是一种常见的数据结构,具有一些基本操作,包括入栈、出栈、获取栈顶元素和判断栈是否为空。

下面将详细介绍这些基本操作。

1. 入栈操作入栈操作是将一个元素添加到链栈的栈顶。

具体步骤如下:(1)创建一个新节点,将要入栈的元素存储在该节点中。

(2)将新节点的next指针指向当前栈顶节点。

(3)将新节点设为新的栈顶节点。

2. 出栈操作出栈操作是将链栈的栈顶元素移除,并返回该元素的值。

具体步骤如下:(1)判断链栈是否为空,若为空则无法进行出栈操作。

(2)将当前栈顶节点的元素值保存到一个临时变量中。

(3)将栈顶节点的next指针指向下一个节点。

(4)释放原来的栈顶节点。

(5)返回保存的临时变量。

3. 获取栈顶元素获取栈顶元素操作是返回链栈的栈顶元素的值,但不移除该元素。

具体步骤如下:(1)判断链栈是否为空,若为空则无法获取栈顶元素。

(2)返回栈顶节点的元素值。

4. 判断栈是否为空判断栈是否为空操作是检查链栈是否为空。

具体步骤如下:(1)若链栈的栈顶节点为NULL,则链栈为空,返回True;否则,返回False。

以上是不带头结点的链栈的基本操作。

下面通过一个简单的示例来演示这些操作的使用。

假设有一个不带头结点的链栈,初始时为空。

我们可以依次进行入栈、出栈、获取栈顶元素和判断栈是否为空的操作。

我们进行入栈操作,依次将元素1、2、3入栈。

此时链栈的状态如下:栈顶->3->2->1->NULL然后,我们进行出栈操作,依次将栈顶的元素移除。

出栈操作的结果为3、2、1。

此时链栈的状态为空。

接着,我们进行获取栈顶元素的操作,发现栈为空,无法获取栈顶元素。

我们进行判断栈是否为空的操作,发现栈为空,返回True。

通过以上示例,我们可以看到不带头结点的链栈的基本操作是非常简单的。

入栈操作将元素添加到栈顶,出栈操作将栈顶元素移除,获取栈顶元素操作返回栈顶元素的值,判断栈是否为空操作检查链栈是否为空。

不带头结点,头部插入法创建链表

不带头结点,头部插入法创建链表

不带头结点,头部插⼊法创建链表#include<stdio.h>#include<stdlib.h>#define ListSize 100typedef int DataType;typedef struct{DataType *data;int length;int size;} Sqlist;void initSqlist(Sqlist *L){L->data = (void*)malloc(ListSize * sizeof(int));if(! L->data) exit(0);L->length = 0;L->size = ListSize;}/*在顺序表的i位置插⼊元素*/void insertSqlist(Sqlist *L,int i,DataType e){int j;DataType *base;if(i<1 || i>L->length+1) exit(0);if(L->length >= L->size){base = (void *) realloc(L->data,(L->length+10)*sizeof(int));if(! base) exit(0);L->data = base;L->size = L->length +10;}for(j = L->length-1;j>= i-1;j--){L->data[j+1] = L->data[j];}L->data[i-1] = e;L->length ++;}/*从顺序表中删除元素*/void delSqlist(Sqlist *L,int i){/*位置是否合法*/int j;if(i<1 || i>L->length +1) exit(0);for(j = i;j < L->length;j++)xx{L->data[j-1] = L->data[j];}L->length --;}int main(){Sqlist L;int i;initSqlist(&L);for(i = 0;i < 15;i++){insertSqlist(&L,i+1,i+1);}for(i = 0;i<15;i++)printf("%d ",L.data[i]);putchar(10);''delSqlist(&L,5);for(i = 0;i<15;i++)printf("%d ",L.data[i]);putchar(10);system("pause");return 0;}上⾯代码实现了顺序表的创建。

单向链表操作详解

单向链表操作详解

单向链表操作详解(一)/*=============================================== 作者:rerli时间:2003-12-05目的:学习单向链表的创建、删除、插入(无序、有序)、输出、排序(选择、插入、冒泡)、反序说明:编译没有任何错误,能生成EXE文件。

这个程序TC2.0中编译生成的EXE文件,在运行输入节点时出现以下错误(TC2.01中没有任何错误):scanf : floating point formats not linkedAbnormal program termination即:struct student中float score字段在输入时,它不认float数格式,而改为long score却可以正常运行。

但是在TC2.01中float score重新编译、链接、运行很正常。

因此,我认为这是TC2.0在结构类型中的Bug.================================================ *//*单向链表的图示:---->[NULL]head图1:空链表---->[p1]---->[p2]...---->[pn]---->[NULL]head p1->next p2->next pn->next图2:有N个节点的链表*/#include <stdlib.h>#include <stdio.h>#define NULL 0#define LEN sizeof(struct student)struct student{long num; /*学号*/float score; /*分数,其他信息可以继续在下面增加字段*/struct student *next; /*指向下一节点的指针*/};int n; /*节点总数*//*==========================功能:创建节点返回:指向链表表头的指针==========================*/struct student *Create(){struct student *head; /*头节点*/struct student *p1=NULL; /*p1保存创建的新节点的地址*/struct student *p2=NULL; /*p2保存原链表最后一个节点的地址*/n = 0; /*创建前链表的节点总数为0:空链表*/p1 = (struct student *)malloc(LEN); /*开辟一个新节点*/p2 = p1; /*如果节点开辟成功,则p2先把它的指针保存下来以备后用*/if (p1 == NULL) /*节点开辟不成功*/{printf("\nCann't create it, try it again in a moment!\n");return NULL;}else /*节点开辟成功*/{head = NULL; /*开始head指向NULL*/printf("Please input %d node -- num,score: ",n+1);scanf("%ld,%f",&(p1->num),&(p1->score)); /*录入数据*/}while(p1->num != 0) /*只要学号不为0,就继续录入下一个节点*/{n += 1; /*节点总数增加1个*/if (n==1) /*如果节点总数是1,则head指向刚创建的节点p1*/{head = p1;/*注意:此时的p2就是p1,也就是p1->next指向NULL。

c语言实现--不带头结点的单链表操作

c语言实现--不带头结点的单链表操作

c语⾔实现--不带头结点的单链表操作1,不带头结点的单链表操作中,除了InitList(),GetElem(),ListInsert(),ListDelete()操作与带头结点的单链表有差别外,其它的操作基本上⼀样。

2,不带头结点单链表⽰意图:链表指针直接指向了⾸元节点,因此在⾸元节点前插⼊数据元素或者删除⾸元节点元素都会改变头指针的值。

3,不带头结点的单链表定义及操作集合,除了插⼊,删除,清空操作需要传递头指针的地址外,基本上⼀样。

头⽂件defs.h1 #ifndef _DEFS_H_2#define _DEFS_H_34 #include<stdio.h>5 #include<malloc.h> //malloc(),free()6 #include<stdlib.h> //exit()78struct LNode9 {10int data;11int * next;12 };13 typedef struct LNode * linklist;1415//操作集合,注意ClearList,ListInsert,ListDelete16void InitList(linklist *L);17void DestroyList(linklist *L);18void ClearList(linklist *L); //这⾥,清空和撤销⼀样19void ListEmpty(linklist L);20int ListLength(linklist L);21int GetElem(linklist L, int i, int *e);22int LocateElem(linklist L, int e);23int PriorElem(linklist L, int cur_e, int *pri_e);24int NextElem(linklist L, int cur_e, int *nex_e);25int ListInsert(linklist *L, int i, int e); //注意在⾸元结点前插⼊时改变头指针26int ListDelete(linklist *L, int i, int *e); //删除⾸元结点时改变头指针27void TravelList(linklist L);28#endif//只要是能够改变头指针的值,均是传递头指针的地址4,InitList操作。

本题要求采用递归方式求不带头结点的单链表的长度。

本题要求采用递归方式求不带头结点的单链表的长度。

本题要求采用递归方式求不带头结点的单链表的长度。

在计算机科学中,递归是一种常见的算法思想,可以应用于各种数据结构和问题求解中。

在单链表中,我们可以使用递归的方式来求解不带头结点的单链表的长度。

本文将深入探讨递归方式求解单链表长度的方法,以及对递归思想的理解和个人观点。

一、递归方式求解不带头结点的单链表长度在单链表中,每个节点都包含一个数据元素和一个指向下一个节点的指针。

如果我们想要求解不带头结点的单链表长度,可以使用递归的方式来实现。

递归的思想是将一个大问题分解为一个或多个与原问题相似的小问题,通过不断地求解小问题,最终达到解决大问题的目的。

为了求解不带头结点的单链表长度,我们可以设计一个递归函数,如下所示:```c++int getLength(Node* node) {if (node == NULL) {return 0; // 递归基}return 1 + getLength(node->next); // 递归式}```以上代码中,getLength函数接受一个节点作为参数,如果节点为空,即表示链表结束,返回长度为0;否则,返回1加上下一个节点的长度,递归地求解整个链表的长度。

使用递归方式求解单链表长度的优点是代码简洁、易于理解,但也需要注意递归深度过大可能导致栈溢出的问题。

在实际应用中,可以根据具体情况选择合适的解决方案。

二、对递归思想的个人理解和观点递归作为一种常见的算法思想,在解决问题时具有一定的灵活性和普适性。

通过将大问题分解为小问题,并不断地求解小问题,最终达到解决大问题的目的。

在算法设计和实现中,递归能够简化代码逻辑,提高代码的可读性和可维护性。

然而,递归也存在一些问题,如递归深度过大可能导致栈溢出、性能较低等。

在实际应用中,需要慎重选择是否使用递归,并结合问题的特点选择合适的解决方案。

总结回顾通过本文的探讨,我们深入了解了递归方式求解不带头结点的单链表长度的方法。

递归思想能够简化问题、提高代码的可读性和可维护性,但也需要注意递归深度过大可能导致的问题。

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

2 He 20 ^
删除操作
例:删除在i=1的位置上的学生
操作前:L
1 Li 18
2 He 20 ^
步骤1: 用q记住第1个结点的地址,再删除q指向的 结点,并释放空间
L
q1
2
Li 18
He 20 ^
q=L; L=q->next; Байду номын сангаасelete q;
删除操作
例:删除在i=2的位置上的学生
操作前:L
➢ 已知条件: 链表的头指针,插入的位置,插入的数据
➢ 操作的结果: 链表上多了一个结点,链表的头指针可能改变。
插入操作
例:在i=2的位置上插入学生数据x(liu,19)
操作前: L
1 Li 18
2 He 20 ^
操作后: L
1 Li 18
2 He 20 ^
liu 19
插入操作
例:在i=2的位置上插入学生数据x(liu,19)
操作前: L
1 Li 18
2 He 20 ^
步骤3: 生成新结点,将数据放入结点,插入到链表中。
L
p K=1
Li 18


s liu 19
He 20 ^
s=new NODE; s->data=x; s->next=L;
L=s;
插入函数
int insertLink(LINK &L, int i, STU x) {
}
删除函数
//删除的不是第1个结点 { q= p->next; p->next =q->next; delete q; return 1; }
s->next=p->next; p->next=s; return 1; }
删除操作
• 功能:将指定位置上的结点删除 ➢ 已知条件:
链表的头指针,删除的位置 ➢ 操作的结果:
链表上少了一个结点,链表的头指针可能改变。
删除操作
例:删除位置为i=1的结点
操作前:L
1 Li 18
操作后:L
1 He 20 ^
初始化操作
功能:创建一个空链表 初始条件:已知头指针变量(没有确定的值) 操作结果:头指针变量为空,发生了改变 操作前: L ? 操作后: L ^
初始化函数
操作前: L ? 操作后: L ^
int initLink(LINK &L) {
L=NULL; return 1; }
插入操作
• 功能:在指定位置插入一个新的结点
操作前: L
1 Li 18
2 He 20 ^
步骤3: 生成新结点,将数据放入结点,插入到链表中。
L
p K=1
Li 18
He 20 ^ s=new NODE;


s->data=x;
s liu 19
s->next=p->next;
p->next=s;
插入操作
例:在i=1位置上插入学生数据x(liu,19)
LINK p,s; int k; p=L; k=1; while(k<i-1 && p!=NULL){k++; p=p->next;} if(k>i-1 || p==NULL)
{ printf(“位置非法,不能插入\n”); return 0; }
s=new NODE; s->data=x; if(i==1) //插入的是第一个结点 { s->next=L; L=s; return 1; } //插入的不是第一个结点
int age;
//存放年龄
}STU;
注意:上面省略了结构体名
链表操作所需自定义的数据类型
结点类型(学生数据类型,指针类型)
指向结点的指针类型
typedef struct node
{
STU data;
//存放学生数据
struct node *next; //存放下一个结点地址
}NODE, *LINK;
操作前:L
1 Li 18
2 He 20 ^
步骤3: 删除p指向结点的下一个结点q,回收q指向的结
点空间 L
p K=1
q①
Li 18 ^ He 20 ^

q= p->next; //① p->next =q->next; //② delete q;
删除函数 int deleteLink(LINK &L, int i)
1 Li 18
2 He 20 ^
步骤2:判断能否进行删除。如果i<1,会出现k>i-1,不能 删除;如果i>=3会出现 p->next为空,不能删除
L
p K=1
Li 18
He 20 ^
if( k>i-1 || p->next==NULL) printf(“位置非法,不能删除\0”);
删除操作
例:删除i=2位置的学生
不带头结点的单向链表的基本操作
不带头结点的单向链表的基本操作
初始化
插入 一个基本操作对应一个函数
删除 遍历 假定链表上存放的是学生的数据(姓名,年龄)
L
Wu 20
Li 18
He 20 ^
链表操作所需自定义的数据类型
学生数据(姓名,年龄)
typedef struct
{
char name[20]; //存放姓名
操作前: L
1 Li 18
2 He 20 ^
步骤2: 判断能否进行插入。如果i<1,会出现k>i-1,不 能插入;如果i>3,会出现p为空,不能插入。
L
p K=1
Li 18
He 20 ^
if(k>i-1 || p==NULL) printf(“位置非法,不能插入\0”);
插入操作
例:在i=2位置上插入学生数据x(liu,19)
1 Li 18
2 He 20 ^
步骤1: 用工作指针p记住第i-1个结点的地址
用k记p指向的结点序号
L
p K=1
Li 18
He 20 ^
p=L; k=1; while( p->next!=NULL && k<i-1)
{ k++; p=p->next; }
删除操作
例:删除i=2位置上的结点
操作前:L
操作前: L
1 Li 18
2 He 20 ^
步骤1: 用工作指针p记住第i-1个结点的地址
用k记p指向的结点序号
L
p K=1
Li 18
He 20 ^
p=L; k=1; while(p!=NULL && k<i-1){k++; p=p->next;}
插入操作
例:在i=2位置上插入学生数据x(liu,19)
{ LINK p,q; int k; p=L; k=1; while(p->next!=NULL && k<i-1) { k++; p=p->next; } if(k>i-1 || p->next==NULL) { printf(“位置非法或链表为空,不能删除\0”); return 0; } if(i==1) //删除第1个结点 { q=L; L=q->next; delete q; return 1; } {……}//删除的不是第1个结点代码在下一页
相关文档
最新文档