0 引言
今天继续数据结构和算法的学习,开启第二章内容的学习线性表。
1 线性表(逻辑结构)
线性表是一种基本的数据结构,其特点是数据元素之间是一对一的线性关系。在线性表中,每个数据元素(除了第一个和最后一个之外)都有一个前驱和一个后继,即每个元素都只有一个直接前驱和一个直接后继。这种结构可以形象地类比为一列排队的人,每个人(除了队首和队尾的人)都有一个前面的人和一个后面的人。
1.1 特点
- 有序性:线性表中的元素具有自然的顺序性,即元素之间是按一定的顺序排列的。
- 一对一的关系:线性表中的每个数据元素(除了第一个和最后一个元素)都有且仅有一个直接前驱和一个直接后继。
1.2 应用
线性表是数据结构中最简单和最常用的一种结构,广泛应用于实现各种更高级的数据结构和算法,如栈、队列、字符串处理等。在实际编程中,根据具体需求选择适当的线性表结构,可以显著影响程序的性能和效率。
2 线性表的物理结构
2.1 顺序存储线性表
用 C 语言来实现一个线性表的顺序存储结构。这里我们创建一个简单的顺序表结构,并提供添加、删除和获取元素的功能。
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 10
typedef struct {
int data[MAX_SIZE];
int length;
} SequentialList;
void initList(SequentialList *list) {
list->length = 0;
}
int insert(SequentialList *list, int index, int value) {
if (list->length == MAX_SIZE) {
printf("List is full\n");
return -1;
}
if (index < 0 || index > list->length) {
printf("Index out of bounds\n");
return -1;
}
for (int i = list->length - 1; i >= index; i--) {
list->data[i + 1] = list->data[i];
}
list->data[index] = value;
list->length++;
return 0;
}
int delete(SequentialList *list, int index) {
if (list->length == 0) {
printf("List is empty\n");
return -1;
}
if (index < 0 || index >= list->length) {
printf("Index out of bounds\n");
return -1;
}
for (int i = index; i < list->length - 1; i++) {
list->data[i] = list->data[i + 1];
}
list->length--;
return 0;
}
int get(SequentialList *list, int index) {
if (index < 0 || index >= list->length) {
printf("Index out of bounds\n");
return -1;
}
return list->data[index];
}
void printList(SequentialList *list) {
for (int i = 0; i < list->length; i++) {
printf("%d ", list->data[i]);
}
printf("\n");
}
int main() {
SequentialList list;
initList(&list);
insert(&list, 0, 10);
insert(&list, 1, 20);
insert(&list, 1, 30);
printList(&list); // 输出: 10 30 20
delete(&list, 1);
printList(&list); // 输出: 10 20
printf("Element at index 1: %d\n", get(&list, 1)); // 输出: Element at index 1: 20
return 0;
}
在这个例子中:
SequentialList
结构体用于存储线性表的数据和长度。initList
函数用于初始化线性表。insert
函数用于在指定位置插入一个元素。delete
函数用于删除指定位置的元素。get
函数用于获取指定位置的元素。printList
函数用于打印线性表的所有元素。
这段代码展示了顺序存储线性表在 C 语言中的基本实现,包括了一些基础的错误检查。需要注意的是,这个实现的数组大小是固定的,实际应用中可能需要动态调整数组的大小以适应不同的需求。
2.2 链式存储线性表
我明白您的担忧,代码格式的确很重要,特别是在C语言这样的语言中,清晰的代码格式可以大大增强代码的可读性和维护性。下面是重新格式化的代码,我将确保它更加整洁和规范:
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构体
typedef struct Node {
int data;
struct Node *next;
} Node;
// 创建新节点
Node* createNode(int data) {
Node *newNode = (Node *)malloc(sizeof(Node));
if (!newNode) {
printf("Memory allocation failed\n");
exit(1);
}
newNode->data = data;
newNode->next = NULL;
return newNode;
}
// 在链表的指定位置插入新节点
void insertNode(Node **head, int data, int position) {
Node *newNode = createNode(data);
if (position == 0) {
newNode->next = *head;
*head = newNode;
} else {
Node *current = *head;
for (int i = 0; current != NULL && i < position - 1; i++) {
current = current->next;
}
if (current == NULL) {
printf("Position out of bounds\n");
} else {
newNode->next = current->next;
current->next = newNode;
}
}
}
// 删除链表中指定位置的节点
void deleteNode(Node **head, int position) {
if (*head == NULL) {
printf("List is empty\n");
return;
}
Node *temp = *head;
if (position == 0) {
*head = temp->next;
free(temp);
} else {
for (int i = 0; temp != NULL && i < position - 1; i++) {
temp = temp->next;
}
if (temp == NULL || temp->next == NULL) {
printf("Position out of bounds\n");
return;
}
Node *next = temp->next->next;
free(temp->next);
temp->next = next;
}
}
// 打印链表
void printList(Node *head) {
while (head != NULL) {
printf("%d -> ", head->data);
head = head->next;
}
printf("NULL\n");
}
// 主函数
int main() {
Node *head = NULL;
insertNode(&head, 10, 0); // List: 10
insertNode(&head, 20, 1); // List: 10 -> 20
insertNode(&head, 30, 2); // List: 10 -> 20 -> 30
printList(head);
deleteNode(&head, 1); // Delete element at position 1: 10 -> 30
printList(head);
// 清理内存
while (head != NULL) {
Node *temp = head;
head = head->next;
free(temp);
}
return 0;
}