数据结构:单链表(LinkList)基本操作的算法描述(C语言)

作者在学习数据结构时,发现鲜有完全按照 C 语言描述的算法操作,这让习惯于写 .c 而不是 .cpp 的初学者很是头疼。本文将基于 C 语言描述算法操作,如有错漏还望大佬们指正。


前言

本文将按照严惠敏所著《数据结构(C语言版)》所做的函数原型声明进行算法描述,由于C语言不支持函数参数中出现取地址符,我将函数参数更改为指针,调用函数时需要使用一级指针。新增了打印函数 PrintList; 单链表的基本操作调用示例将在本文后给出。


一、单链表基本操作的函数声明

//构造一个空的单链表 L 并初始化
extern Status InitList(LinkList* L);
//销毁单链表 L
extern Status DestroyList(LinkList* L);
//将 L 重置为空表
extern Status ClearList(LinkList L);
//若 L 为空表,则返回 TRUE,否则返回 FALSE
extern Status ListEmpty(LinkList L);
//返回 L 中数据元素个数
extern int ListLength(LinkList L);
//用 e 返回 L 中第 i 个数据元素的值
extern Status GetElem(LinkList L, int i, ElemType* e);
//返回 L 中第一个与 e 满足关系 compare() 的数据元素的位序,若这样的数据元素不存在,则返回 0
extern int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType));
//若 cur_e 是 L 的数据元素,且不是第一个,则用 pre_e 返回它的前驱,否则操作失败,pre_e 无定义
extern Status PriorElem(LinkList L, ElemType cur_e, ElemType* pre_e);
//若 cur_e 是 L 的数据元素,且不是最后一个,则用 next_e 返回它的后继,否则操作失败,next_e 无定义
extern Status NextElem(LinkList L, ElemType cur_e, ElemType* next_e);
//在带头结点的单链线性表 L 中第 i 个位置之前插入元素 e
extern Status ListInsert(LinkList* L, int i, ElemType e);
//在带头结点的单链线性表 L 中,删除第 i 个元素,并用 e 返回其值
extern Status ListDelete(LinkList* L, int i, ElemType* e);
//打印单链表
extern Status PrintList(LinkList L);
//逆位序输入 n 个元素的值,建立带表头结点的单链线性表 L
extern void CreateList(LinkList* L, int n);
//归并两个非递减排列的线性表 La、Lb 至 Lc,Lc也是非递减排列的
extern void MergeList(LinkList La, LinkList Lb, LinkList* Lc);

二、单链表基本操作的完整描述

/* 单链表*/
#include <stdio.h>
#include <stdlib.h>
#define TRUE  			1
#define FALSE 			0
#define OK    			1
#define ERROR 			0
#define INFEASIBLE 		-1
#define OVERFLOW   		-2
#define EQUAL			0
#define LOWER			1
#define HIGHER			2

typedef int Status;
typedef int ElemType;
typedef struct LNode {
    ElemType data;
    struct LNode* next;
} LNode, * LinkList;

//--------单链表的基本操作的函数声明--------

//构造一个空的单链表 L 并初始化
extern Status InitList(LinkList* L);
//销毁单链表 L
extern Status DestroyList(LinkList* L);
//将 L 重置为空表
extern Status ClearList(LinkList L);
//若 L 为空表,则返回 TRUE,否则返回 FALSE
extern Status ListEmpty(LinkList L);
//返回 L 中数据元素个数
extern int ListLength(LinkList L);
//用 e 返回 L 中第 i 个数据元素的值
extern Status GetElem(LinkList L, int i, ElemType* e);
//返回 L 中第一个与 e 满足关系 compare() 的数据元素的位序,若这样的数据元素不存在,则返回 0
extern int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType));
//若 cur_e 是 L 的数据元素,且不是第一个,则用 pre_e 返回它的前驱,否则操作失败,pre_e 无定义
extern Status PriorElem(LinkList L, ElemType cur_e, ElemType* pre_e);
//若 cur_e 是 L 的数据元素,且不是最后一个,则用 next_e 返回它的后继,否则操作失败,next_e 无定义
extern Status NextElem(LinkList L, ElemType cur_e, ElemType* next_e);
//在带头结点的单链线性表 L 中第 i 个位置之前插入元素 e
extern Status ListInsert(LinkList* L, int i, ElemType e);
//在带头结点的单链线性表 L 中,删除第 i 个元素,并用 e 返回其值
extern Status ListDelete(LinkList* L, int i, ElemType* e);
//打印单链表
extern Status PrintList(LinkList L);
//逆位序输入 n 个元素的值,建立带表头结点的单链线性表 L
extern void CreateList(LinkList* L, int n);
//归并两个非递减排列的线性表 La、Lb 至 Lc,Lc也是非递减排列的
extern void MergeList(LinkList La, LinkList Lb, LinkList* Lc);

Status InitList(LinkList* L) {
    (*L) = (LinkList)malloc(sizeof(LNode));
    if (!(*L)) exit(OVERFLOW);
    (*L)->next = NULL;
    return OK;
}// InitList

Status DestroyList(LinkList* L) {
    LinkList q;
    while (*L) {
        q = (*L)->next;
        free(*L);
        *L = q;
    }
    return OK;
}// DestroyList

Status ClearList(LinkList L) {
    LinkList p = L->next;
    L->next = NULL;
    DestroyList(&p);
}// ClearList

Status ListEmpty(LinkList L) {
    if (L->next) return TRUE;
    else return FALSE;
}// ListEmpty

int ListLength(LinkList L) {
    int i = 0;
    LinkList p = L->next;
    while (p) {
        p = p->next;
        i++;
    }
    return i;
}// ListLength

Status GetElem(LinkList L, int i, ElemType* e) {
    LinkList p = L->next; int j = 1;
    while (j < i && p) p = p->next;
    if (j > i || !p) return ERROR;
    *e = p->data;
    return OK;
}// GetElem

int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType)) {
    int i = 1;
    LinkList p = L->next;
    while (p && (*compare)(p->data, e)) ++i;
    if (i <= ListLength(L)) return i;
    else return 0;
}// LocateElem

Status PriorElem(LinkList L, ElemType cur_e, ElemType* pre_e) {
    LinkList p = L->next;
    while (p && p->next) {
        if (p->next->data == cur_e) {
            *pre_e = p->data;
            return OK;
        }
        p = p->next;
    }
    return ERROR;
}// PriorElem

Status NextElem(LinkList L, ElemType cur_e, ElemType* next_e) {
    LinkList p = L->next;
    while (p && p->next) {
        if (p->data == cur_e) {
            *next_e = p->next->data;
            return OK;
        }
        p = p->next;
    }
    return ERROR;
}// NextElem

Status ListInsert(LinkList* L, int i, ElemType e) {
    LinkList p = *L, s; int j = 0;
    while (p && j < i - 1) { p = p->next; ++j; }
    if (!p || j > i - 1) return ERROR;
    s = (LinkList)malloc(sizeof(LNode));
    s->data = e; s->next = p->next;
    p->next = s;
    return OK;
}// ListInsert

Status ListDelete(LinkList* L, int i, ElemType* e) {
    LinkList p = *L, q; int j = 0;
    while (p->next && j < i - 1) { p = p->next; ++j; }
    if (!(p->next) || j > i - 1) return ERROR;
    q = p->next; p->next = q->next;
    *e = q->data; free(q);
    return OK;
}// ListDelete

Status PrintList(LinkList L) {
    if (!L->next) return ERROR;
    LinkList p = L->next;
    while (p) {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
    return OK;
}// PrintList

void CreateList(LinkList* L, int n) {
    L = (LinkList*)malloc(sizeof(LNode));
    (*L)->next = NULL;
    LinkList p;
    for (int i = n; i > 0; --i) {
        p = (LinkList)malloc(sizeof(LNode));
        scanf("%d", &p->data);
        p->next = (*L)->next; (*L)->next = p;
    }
}// CreatList

void MergeList(LinkList La, LinkList Lb, LinkList* Lc) {
    LinkList pa = La->next, pb = Lb->next, pc;
    *Lc = pc = La;
    while (pa && pb) {
        if (pa->data <= pb->data) {
            pc->next = pa; pc = pa; pa = pa->next;
        }
        else { pc->next = pb; pc = pb; pb = pb->next; }
    }
    pc->next = pa ? pa : pb;
    free(Lb);
}// MergeList

三、调用示例

int main() {
    LinkList L;
    int e = 0, pre_e = 0, nxt_e = 0;
    InitList(&L);
    ListInsert(&L, 1, 1);
    ListInsert(&L, 2, 2);
    ListInsert(&L, 3, 3);
    printf("List example: ");
    PrintList(L);
    PriorElem(L, 2, &pre_e);
    NextElem(L, 2, &nxt_e);
    printf("PriorElem(L, 2, pre_e): %d\n", pre_e);
    printf("NextElem(L, 2, nxt_e): %d\n", nxt_e);
    ListDelete(&L, 2, &e);
    printf("ListDelete(&L, 2, &e): %d\n", e);
    printf("Deleted List: ");
    PrintList(L);
}

终端输出结果如下:

List example: 1 2 3 
PriorElem(L, 2, pre_e): 1
NextElem(L, 2, nxt_e): 3
ListDelete(&L, 2, &e): 2
Deleted List: 1 3 

总结

以上是单链表的基本操作的算法描述,更多数据结构的算法描述还在更新中,敬请关注作者专栏。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值