2.1线性表
2.1.1什么是线性表?
线性表(Linear List):由同类型数据元素构成有序序列的线性结构。
特点:1.表中元素个数称为线性表的长度;
2.线性表没有元素时称为空表;
3.表的起始位置称为表头,表的结束位置称为表尾。
2.1.2线性表的抽象数据类型描述
类型名称:线性表(List)
数据对象集:线性表是n(n>=0)个元素构成的有序序列(a1,a2,a3,…an)
操作集:
1.初始化一个空线性表
2.根据位序k返回相应元素
3.在线性表中查找对象第一次出现的位置
4.在位序i前插入一个新元素x
5.删除指定位序的元素
6.返回线性表的长度
2.1.3线性表的顺序存储实现
很简单,如对象数组。
2.1.4线性表的链式存储实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*链表中元素的结构体定义,以下只是一个例子*/
typedef struct student{
char num[20]; //学号
char name[20]; //姓名
char sex[5]; //性别
int age; //年龄
} ElementType;
/*链表的定义*/
typedef struct LNode * List; //链表结点的指针
struct LNode { //链表的结点
ElementType Data;
List Next;
};
struct LNode L; //链表
List PtrL; //链表的头指针
/*操作集的声明*/
int Length(List PtrL); //返回链表长度
List FindKth(int K, List PtrL); //按序号查找
List Find(ElementType X, List PtrL); //按值查找
List Insert(ElementType X, int i, List PtrL); //在序号i处插入
List Delete(int i, List PtrL); //删除序号i处的元素
List initialize(); //初始化一个头结点
int Length(List PtrL) {
List P = PtrL; // p指向表的第一个结点
int j = 0;
while (P) {
P = P->Next;
j++; //当前p指向第j个结点
}
return j;
}
List FindKth(int K, List PtrL) {
List P = PtrL; // p指向表的第一个结点
int i = 1;
while (P != NULL && i < K) {
P = P->Next;
i++;
}
if (i == K) return P; //找到返回p的指针
else return NULL; //找不到返回空
}
List Find(ElementType X, List PtrL) {
List P = PtrL; // p指向表的第一个结点
while (P != NULL) {
if (strcmp(P->Data.num, X.num) == 0 &&
strcmp(P->Data.name, X.name) == 0 &&
strcmp(P->Data.sex, X.sex) == 0 &&
P->Data.age == X.age) {
return P;
}
P = P->Next;
}
return NULL;
}
List Insert(ElementType X, int i, List PtrL) {
List P, S;
if (i == 1) { // i==1是在表头插入
S = (List)malloc(sizeof(struct LNode));
S->Data = X;
S->Next = PtrL;
return S; //直接返回表头
}
P = FindKth(i-1, PtrL); //查找第i-1个结点
if (P == NULL) {
printf("parameter error!");
return NULL;
} else {
S = (List)malloc(sizeof(struct LNode));
S->Data = X; //装载元素
S->Next = P->Next; //将结点插入在 i-1 ~ i 之间
P->Next = S;
return PtrL;
}
}
List Delete(int i, List PtrL) {
List P, S;
if (i == 1) { //要删除的结点是第一个结点
S = PtrL;
if (PtrL != NULL) PtrL = PtrL->Next;
else return NULL;
free(S);
return PtrL;
}
P = FindKth(i-1, PtrL); //查找第i-1个结点
if (P == NULL) {
printf("第%d个结点不存在", i-1);
return NULL;
} else if (P->Next == NULL) {
printf("第%d个结点不存在", i);
return NULL;
} else {
S = P->Next; // S指向要删除的结点
P->Next = S->Next; //将i-1结点的键连接上i的下一个结点
free(S);
return PtrL;
}
}
List initialize() { //初始化一个头结点默认值为0
ElementType defau = {
.num = "123456789", //学号
.name = "lihua", //姓名
.sex = "man", //性别
.age = 18 //年龄
};
List list = (List)malloc(sizeof(struct LNode));
list->Data = defau;
list->Next = NULL;
return list;
}
int main() {
// 测试代码可以放在这里
PtrL = initialize();
printf("Initialized list with head: %s, %s, %s, %d\n", PtrL->Data.num, PtrL->Data.name, PtrL->Data.sex, PtrL->Data.age);
ElementType newStudent = {
.num = "2",
.name = "zhangsan",
.sex = "male",
.age = 20
};
PtrL = Insert(newStudent, 2, PtrL);
printf("Length of list: %d\n", Length(PtrL));
List found = Find(newStudent, PtrL);
if (found) {
printf("Found student: %s, %s, %s, %d\n", found->Data.num, found->Data.name, found->Data.sex, found->Data.age);
} else {
printf("Student not found.\n");
}
PtrL = Delete(1, PtrL);
printf("Length of list after deletion: %d\n", Length(PtrL));
return 0;
}
2.1.5广义表
广义表(Deneralized List)
是线性表的推广;
对于线性表而言,n个元素都是基本的单元素;
在广义表中,这些元素不仅可以是单元素也可以是另一个广义表。
2.1.6多重链表(广义表的实现)
链表中的节点可能同时隶属于多个链表。
多重链表中节点的指针域会有多个,如其中包含了next与sublist两个指针域。
但是包含了两个指针域的链表并不一定是多重链表,比如双向链表就不是多重链表。
且:多重链表有个泛的用途就是,诸如图,树这样相对复杂的数据结构都可以采用多重链表方式来实现存储。