不带头结点的单链表头插法和尾插法建立
时间: 2023-08-28 20:06:46 浏览: 176
好的,我可以为你介绍一下不带头结点的单链表头插法和尾插法的建立方法。
不带头结点的单链表是指链表的第一个节点就是存储数据的节点,而不是一个空的头结点。
首先,我们先来介绍头插法建立单链表的方法。具体步骤如下:
1. 定义一个指向链表头节点的指针变量head,初始化为NULL。
2. 读入一个新节点的数据,创建一个新节点并用该数据进行初始化。
3. 将新节点插入到链表的最前面,使其成为新的头节点。具体操作为:将新节点的next指针指向head,然后将head指针指向新节点。
4. 重复步骤2和3,直到读入的数据为结束标志。
头插法建立单链表的示意图如下所示:
```
NULL <- 1 <- 2 <- 3 <- NULL
```
接下来,我们再来介绍尾插法建立单链表的方法。具体步骤如下:
1. 定义一个指向链表头节点的指针变量head,初始化为NULL。
2. 定义一个指向链表尾节点的指针变量tail,初始化为NULL。
3. 读入一个新节点的数据,创建一个新节点并用该数据进行初始化。
4. 如果head指针为NULL,则将head和tail指针都指向新节点。
5. 如果head指针不为NULL,则将tail节点的next指针指向新节点,然后将tail指针指向新节点。
6. 重复步骤3到5,直到读入的数据为结束标志。
尾插法建立单链表的示意图如下所示:
```
NULL <- 1 <- 2 <- 3 <- NULL
```
相关问题
//1.创建带头结点的单链表(尾插法) LinkList createTail(char*);
在C语言中,创建带头结点的单链表(也称为动态链表)并使用尾插法通常涉及以下几个步骤:
1. 定义结构体表示链表节点,包含数据域和指向下一个节点的指针:
```c
typedef struct Node {
char data; // 存储字符的数据域
struct Node* next; // 指向下一个节点的指针
} Node;
```
2. 创建一个函数,接受一个字符指针作为参数,返回链表头结点的指针。这个函数首先分配一个新的节点,然后将其设置为头结点,同时初始化`next`指针指向空(NULL):
```c
Node* createTail(char* str) {
if (str == NULL) return NULL; // 如果传入的字符串为空,直接返回NULL
// 分配新的节点内存
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL) { // 内存分配失败时返回NULL
perror("Memory allocation failed");
return NULL;
}
// 初始化新节点的数据域
newNode->data = *str;
// 设置头结点的 next 指针
newNode->next = NULL; // 头结点的 next 通常是空指针
// 如果字符串不为空,继续处理剩余的字符
if (*str != '\0') {
Node* current = newNode; // 当前节点初始化为新节点
while (*(++str)) { // 遍历字符串,直到遇到'\0'为止
Node* newNode = (Node*)malloc(sizeof(Node)); // 分配新节点
if (newNode == NULL) {
free(current); // 释放当前已分配的节点,然后退出循环
perror("Memory allocation failed");
return NULL;
}
newNode->data = *str;
newNode->next = current->next; // 将新节点的 next 指向当前节点
current->next = newNode; // 更新当前节点的 next 指针
current = newNode; // 移动到新插入的节点
}
}
return newNode;
}
```
编写函数deln,具有删除链表中第n个结点的功能。再编写主函数,按输入顺序建立不带头结点的职工信息单链表,然后调用del函数删除某个职工的信息,并输出删除后的职工信息表中的职工信息。假设链表结构如下: struct staff { char num[6]; //职工工号 char name[20]; //职工姓名 double wage; //职工工资 };
以下是针对您问题的代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NUM 6
#define MAX_NAME 20
struct staff {
char num[MAX_NUM]; //职工工号
char name[MAX_NAME]; //职工姓名
double wage; //职工工资
struct staff *next; //指向下一个职工的指针
};
struct staff *create_staff(char *num, char *name, double wage) {
struct staff *s = (struct staff*) malloc(sizeof(struct staff));
strcpy(s->num, num);
strcpy(s->name, name);
s->wage = wage;
s->next = NULL;
return s;
}
struct staff *create_list() {
struct staff *head = NULL, *tail = NULL;
char num[MAX_NUM], name[MAX_NAME];
double wage;
int n, i;
printf("请输入职工数量:");
scanf("%d", &n);
printf("请分别输入职工工号、姓名和工资:\n");
for (i = 0; i < n; i++) {
scanf("%s %s %lf", num, name, &wage);
struct staff *s = create_staff(num, name, wage);
if (tail == NULL) {
head = s;
tail = s;
} else {
tail->next = s;
tail = s;
}
}
return head;
}
struct staff *deln(struct staff *head, int n) {
if (head == NULL) {
printf("链表为空!\n");
return NULL;
}
if (n <= 0) {
printf("无效的职工编号!\n");
return head;
}
if (n == 1) {
struct staff *p = head->next;
free(head);
return p;
}
struct staff *p = head;
int i;
for (i = 1; i < n - 1 && p != NULL; i++) {
p = p->next;
}
if (p == NULL || p->next == NULL) {
printf("无效的职工编号!\n");
return head;
}
struct staff *q = p->next;
p->next = q->next;
free(q);
return head;
}
void print_list(struct staff *head) {
printf("职工信息表:\n");
printf(" 编号 姓名 工资\n");
struct staff *p = head;
while (p != NULL) {
printf("%6s %6s %8.2lf\n", p->num, p->name, p->wage);
p = p->next;
}
}
int main() {
struct staff *head = create_list();
print_list(head);
int n;
printf("请输入要删除的职工编号:");
scanf("%d", &n);
head = deln(head, n);
print_list(head);
return 0;
}
```
在这个实现中,我们定义了 `struct staff` 结构体表示职工信息,其中包含职工工号、姓名和工资三个字段,以及一个指向下一个职工的指针 `next`。我们编写了 `create_staff` 函数用于创建一个新的职工信息对象,以及 `create_list` 函数用于按输入顺序建立职工信息链表。在 `create_list` 函数中,我们先输入职工数量,然后循环读入每个职工的信息,创建相应的职工信息对象,并将其加入链表中。这里采用了尾插法来构建链表,以便快速插入新的节点。
我们还编写了 `deln` 函数,用于删除链表中第 n 个职工。在实现中,我们需要考虑一些特殊的情况。如果链表为空,则无法删除,函数直接返回 NULL。如果 n 小于等于 0,或者大于链表长度,则视为无效的职工编号。如果 n 等于 1,则需要特殊处理,因为此时需要删除链表头节点。否则,我们需要遍历链表找到第 n - 1 个节点,然后修改其 next 指针,以便跳过待删除节点。注意,我们需要在删除节点之前先保存其指向的下一个节点,否则无法正确修改链表。
最后,我们编写了 `print_list` 函数,用于按照格式输出职工信息表中的所有职工信息。在主函数中,我们先调用 `create_list` 函数创建职工信息链表,然后调用 `print_list` 函数输出链表中的所有职工信息。接着,我们读入要删除的职工编号,调用 `deln` 函数删除该职工信息节点,并输出删除后的职工信息表中的所有职工信息。
需要注意的是,这个实现中并没有对输入进行严格的错误检查,例如没有判断输入的职工工号和姓名是否超出了预定的长度,也没有判断输入的工资是否为非负数。在实际应用中,我们需要根据实际需求进行适当的修改和完善。
阅读全文