定义-“逻辑结构”
线性表(Linear List)是具有相同数据类型的n (n>=20) 个数据元素的有限序列,其中n为表长,当n= 0时线性表是一个空表。若用L命名线性表,则其一般表示为
几个概念:
是线性表中的“第i个”元素线性表中的位序
是表头元素;是表尾元素。
除第一个元素外,每个元素有且仅有一个直接前驱:除最后一个元素外,每个元素有且仅有一个直接后继
基本操作-“运算”
线性表的基本操作包括创建、销毁、插入、删除、查找、遍历等。
以下是用C语言实现线性表的基本操作代码:
顺序表:
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
typedef struct{
int data[MAXSIZE];
int length;
}SqList;
// 初始化函数
void InitList(SqList *L){
L->length = 0;
}
// 插入元素函数
int ListInsert(SqList *L, int pos, int e){
// 检查插入位置是否合法
if(pos < 1 || pos > L->length+1){
return 0;
}
// 检查是否空间不足
if(L->length >= MAXSIZE){
return 0;
}
// 移动元素以腾出插入位置
for(int i=L->length; i >= pos; i--){
L->data[i] = L->data[i-1];
}
// 插入元素
L->data[pos-1] = e;
L->length++;
return 1;
}
// 删除元素函数
int ListDelete(SqList *L, int pos){
// 检查删除位置是否合法
if(pos < 1 || pos > L->length){
return 0;
}
// 移动元素以覆盖删除位置
for(int i=pos; i <= L->length; i++){
L->data[i-1] = L->data[i];
}
L->length--;
return 1;
}
// 查找元素函数
int ListSearch(SqList *L, int e){
// 遍历列表查找元素
for(int i=0; i < L->length; i++){
if(L->data[i] == e){
return i+1; // 返回元素在表中的位置
}
}
return 0; // 表示查找失败
}
// 输出表中元素函数
void ListPrint(SqList *L){
for(int i=0; i < L->length; i++){
printf("%d ", L->data[i]);
}
printf("\n");
}
int main(){
SqList L;
InitList(&L);
int n, pos, e;
printf("请输入初始元素个数:");
scanf("%d", &n);
printf("请输入初始元素:");
for(int i=1; i <= n; i++){
scanf("%d", &e);
ListInsert(&L, i, e);
}
printf("初始线性表为:");
ListPrint(&L);
printf("请输入要插入的元素位置和元素值:");
scanf("%d %d", &pos, &e);
if(ListInsert(&L, pos, e)){
printf("插入成功,插入后的线性表为:");
ListPrint(&L);
}
else{
printf("插入失败!\n");
}
printf("请输入要删除的元素位置:");
scanf("%d", &pos);
if(ListDelete(&L, pos)){
printf("删除成功,删除后的线性表为:");
ListPrint(&L);
}
else{
printf("删除失败!\n");
}
printf("请输入要查找的元素值:");
scanf("%d", &e);
pos = ListSearch(&L, e);
if(pos){
printf("元素%d在表中的位置为:%d\n", e, pos);
}
else{
printf("元素%d不在表中!\n", e);
}
return 0;
}
链表:
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode{
int data;
struct LNode *next;
}LNode, *LinkList;
// 初始化链表
void InitList(LinkList *L){
*L = (LinkList)malloc(sizeof(LNode));
(*L)->next = NULL;
}
// 在链表的指定位置插入元素
int ListInsert(LinkList L, int pos, int e){
LinkList p = L, s;
int i = 0;
// 遍历到指定位置
while(p && i < pos-1){
p = p->next;
i++;
}
if(!p || i > pos-1){
return 0; // 插入失败
}
s = (LinkList)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return 1; // 插入成功
}
// 删除链表中的指定元素
int ListDelete(LinkList L, int pos){
LinkList p = L, q;
int i = 0;
// 遍历到指定位置
while(p->next && i < pos-1){
p = p->next;
i++;
}
if(!p->next || i > pos-1){
return 0; // 删除失败
}
q = p->next;
p->next = q->next;
free(q); // 释放空间
return 1; // 删除成功
}
// 查找链表中的指定元素
LinkList ListSearch(LinkList L, int e){
LinkList p = L->next;
while(p && p->data != e){
p = p->next;
}
return p; // 返回查找元素的地址
}
// 打印链表中的所有元素
void ListPrint(LinkList L){
LinkList p = L->next;
while(p){
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main(){
LinkList L;
InitList(&L);
int n, pos, e;
printf("请输入初始元素个数:");
scanf("%d", &n);
printf("请输入初始元素:");
for(int i=1; i <= n; i++){
scanf("%d", &e);
ListInsert(L, i, e);
}
printf("初始线性表为:");
ListPrint(L);
printf("请输入要插入的元素位置和元素值:");
scanf("%d %d", &pos, &e);
if(ListInsert(L, pos, e)){
printf("插入成功,插入后的线性表为:");
ListPrint(L);
}
else{
printf("插入失败!\n");
}
printf("请输入要删除的元素位置:");
scanf("%d", &pos);
if(ListDelete(L, pos)){
printf("删除成功,删除后的线性表为:");
ListPrint(L);
}
else{
printf("删除失败!\n");
}
printf("请输入要查找的元素值:");
scanf("%d", &e);
LinkList q = ListSearch(L, e);
if(q){
printf("元素%d在表中的位置为:%p\n", e, q);
}
else{
printf("元素%d不在表中!\n", e);
}
return 0;
}
下面是每个函数和操作的详细注释:
- InitList: 初始化链表,为链表分配一个头节点,并将其next指针设置为NULL。
- ListInsert: 在链表的指定位置插入一个元素。首先遍历到指定位置,然后创建一个新的节点,并将其插入到当前节点的后面。
- ListDelete: 删除链表中的指定元素。遍历到指定位置,然后删除当前节点的下一个节点。
- ListSearch: 查找链表中的指定元素。遍历链表,如果找到则返回该元素的地址,否则返回NULL。
- ListPrint: 打印链表中的所有元素。遍历链表,并打印每个节点的data域。
- main: 主函数,用于测试上述操作。首先初始化链表,然后进行插入、删除和查找操作,并打印结果。
Tips:
- 对数据的操作(记忆思路)--创销、增删改查
- c语言函数的定义--<返回值类型>函数名(<参数1类型>参数1,<参数2类型>参数2,......)
- 实际开发中,可根据实际需求定义其他的基本操作
- 函数名和参数的形式、命名都可改变(Reference:严蔚敏版《数据结构》)