线性表实现

本文介绍线性表及单链表的基本操作实现,包括顺序表的创建、增删改查等,并演示单链表的创建、遍历、删除最大节点等核心功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 线性表–顺序表–增删改查–C 版本
#include <stdio.h>
#include <stdlib.h>

#define  MaxSize 50
typedef int ElemenType;

//线性表--1.0 顺序表---类似数组的方式---默认空间分配出冗余
typedef struct 
{
    ElemenType  data[MaxSize];
    int length;
}SqList;

//城市表 区号--城市名 -- 说明 (010--beijing--首都)


//建立顺序表
void CreateList(SqList* &L, ElemenType a[], int n) //这里是对指针的引用,传递进来的是指针,如果形参为指针,那无法赋值为指针
{
    int i;
    L = (SqList*)malloc(sizeof(SqList)); //new
    for (i = 0; i < n; i++)
        L->data[i] = a[i];
    L->length = n;
}
//初始化线性表InitList(L)
void InitList(SqList* &L)
{
    L = (SqList*)malloc(sizeof(SqList));
    L->length = 0;
}
//销毁线性表--释放空间
void DestroyList(SqList* &L)
{
    free(L); 
}
//判空
bool ListEmpty(SqList* &L)
{
    return (L->length == 0);
}
//求长度
int ListLength(SqList* &L)
{
    return L->length;
}
//输出线性表
void DispList(SqList* &L)
{
    int i;
    if (ListEmpty(L))
        return;
    for (i = 0; i < L->length; i++)
        printf("%d\n", L->data[i]);
    printf("\n");
}
//求某个位置上数据元素
ElemenType e;
bool GetElem(SqList* &L, int i, ElemenType& e)
{
    if (i < 1 || i > L->length)
        return false;
    e = L->data[i - 1];
    return true;
}
//按元素值查找,是否出现,并返回位置
int LocateElem(SqList*L, ElemenType e)
{
    int i = 0;
    while (i < L->length && L->data[i] != e)
        i++;
    if (i >= L->length)
        return 0;
    else
        return i + 1;
}
//插入,在某个位置上插入e,后面位置必须后移,最后长度+1
bool ListInsert(SqList* &L, int i, ElemenType e)
{
    int j;
    if (i<1 || i > L->length + 1)
        return false;
    i--;//逻辑序号,转化为物理序号
    for (j = L->length;j > i;j--)
        L->data[j] = L->data[j - 1];
    L->data[i] = e;
    L->length++;
    return true;
}
//删除某个元素
bool ListDelete(SqList* &L, int i, ElemenType& e)
{
    int j;
    if (i<1 || i > L->length)
        return false;
    i--;//逻辑序号,转化为物理序号
    e = L->data[i];
    for (j = i;j < L->length-1;j++)
        L->data[j] = L->data[j + 1];
    L->length--;
    return true;
}
//将线性表中所有某个元素全部删除,方法1
void Delnode1(SqList* &L, ElemenType x)
{
    int i;
    ElemenType e;//删除的元素保存出来
    while ((i = LocateElem(L, x)) > 0)
    {
        ListDelete(L, i, e);
        }
}
//复杂度为O(n平方)

//////方法2,减小复杂度
void Delnode2(SqList* &L, ElemenType x)
{
    int k = 0;//k记录非x 的元素个数
    for (int i = 0; i < L->length;i++)
    {
        if (L->data[i] != x)
        {
            L->data[k] = L->data[i];
            k++;
        }
    }
        L->length = k;  
}

int main()
{
    SqList* sq; //野指针
    InitList(sq);
    ElemenType x[6] = { 2,8,7,2,4,2 };
    CreateList(sq, x, 6);
    DispList(sq);
    ListInsert(sq,7,100);
    DispList(sq);
    ElemenType y;
    ListDelete(sq, 3, y);
    printf("%d\n",LocateElem(sq, y));
    DispList(sq);
    printf("%d\n", y);
    ListInsert(sq, 7, 200);
    ListInsert(sq, 8, 300);
    DispList(sq);
    Delnode1(sq, 2);
    DispList(sq);


    return 0;
}
  • 线性表–顺序表–分离数据
    这里写图片描述
    这里写图片描述
    这里写图片描述
#include <stdio.h>
#include <stdlib.h>

#define  MaxSize 50
typedef int ElemenType;

//线性表--1.0 顺序表---类似数组的方式---默认空间分配出冗余
typedef struct 
{
    ElemenType  data[MaxSize];
    int length;
}SqList;

//城市表 区号--城市名 -- 说明 (010--beijing--首都)


//建立顺序表
void CreateList(SqList* &L, ElemenType a[], int n) //这里是对指针的引用,传递进来的是指针,如果形参为指针,那无法赋值为指针
{
    int i;
    L = (SqList*)malloc(sizeof(SqList)); //new
    for (i = 0; i < n; i++)
        L->data[i] = a[i];
    L->length = n;
}
//初始化线性表InitListLvoid InitList(SqList* &L)
{
    L = (SqList*)malloc(sizeof(SqList));
    L->length = 0;
}
//销毁线性表--释放空间
void DestroyList(SqList* &L)
{
    free(L); 
}
//判空
bool ListEmpty(SqList* &L)
{
    return (L->length == 0);
}
//求长度
int ListLength(SqList* &L)
{
    return L->length;
}
//输出线性表
void DispList(SqList* &L)
{
    int i;
    if (ListEmpty(L))
        return;
    for (i = 0; i < L->length; i++)
        printf("%d\n", L->data[i]);
    printf("\n");
}
//求某个位置上数据元素
ElemenType e;
bool GetElem(SqList* &L, int i, ElemenType& e)
{
    if (i < 1 || i > L->length)
        return false;
    e = L->data[i - 1];
    return true;
}
//按元素值查找,是否出现,并返回位置
int LocateElem(SqList*L, ElemenType e)
{
    int i = 0;
    while (i < L->length && L->data[i] != e)
        i++;
    if (i >= L->length)
        return 0;
    else
        return i + 1;
}
//插入,在某个位置上插入e,后面位置必须后移,最后长度+1
bool ListInsert(SqList* &L, int i, ElemenType e)
{
    int j;
    if (i<1 || i > L->length + 1)
        return false;
    i--;//逻辑序号,转化为物理序号
    for (j = L->length;j > i;j--)
        L->data[j] = L->data[j - 1];
    L->data[i] = e;
    L->length++;
    return true;
}
//删除某个元素
bool ListDelete(SqList* &L, int i, ElemenType& e)
{
    int j;
    if (i<1 || i > L->length)
        return false;
    i--;//逻辑序号,转化为物理序号
    e = L->data[i];
    for (j = i;j < L->length-1;j++)
        L->data[j] = L->data[j + 1];
    L->length--;
    return true;
}
//将线性表中所有某个元素全部删除,方法1
void Delnode1(SqList* &L, ElemenType x)
{
    int i;
    ElemenType e;//删除的元素保存出来
    while ((i = LocateElem(L, x)) > 0)
    {
        ListDelete(L, i, e);
        }
}
//复杂度为O(n平方)

//////方法2,减小复杂度
void Delnode2(SqList* &L, ElemenType x)
{
    int k = 0;//k记录非x 的元素个数
    for (int i = 0; i < L->length;i++)
    {
        if (L->data[i] != x)
        {
            L->data[k] = L->data[i];
            k++;
        }
    }
        L->length = k;  
}
//分离元素,以第一个元素为分界线,将所有小于它的元素移到该元素的前面,将所有大于它的元素移到该元素的后面
//解法1:
//以data[0]为基准。
//从区间两端交替向中间扫描,直到 i=j ,每轮循环
// 从右到左,找一个小于等于pivot的元素
// 从左到右,找一个大于pivot的元素
// 然后将L->data[i] 和 L->data[j]交换
//退出循环,将L->data[0]和L->data[j]交换
void move1(SqList* &L)
{
    int i = 0, j = L->length - 1;
    ElemenType pivot = L->data[0];
    ElemenType tmp;
    while (i < j)
    {
        //从右到左,找到第一个小于pivot的元素
        while (i < j && L->data[j] > pivot)
            j--;
        //从左到右,找到第一个大于pivot的元素
        while (i < j && L->data[i] <= pivot)
            i++;
        //交换
        if (i < j)
        {
            tmp = L->data[i];
            L->data[i] = L->data[j];
            L->data[j] = tmp;
        }
    }
    //退出循环,将L->data[0]和data[j]交换
    tmp = L->data[0];
    L->data[0] = L->data[j];
    L->data[j] = tmp;
}
//方法2,交替进行,一次左一次右,直接将数据互换
void move2(SqList* &L)
{
    int i = 0, j = L->length - 1;
    ElemenType pivot = L->data[0];
    while (i < j)
    {
        while (i < j && L->data[j] > pivot)
            j--;
        L->data[i] = L->data[j];
        i++;
        while (i < j && L->data[i] < pivot)
            i++;
        L->data[j] = L->data[i];
        j--;
    }
    L->data[i] = pivot;
    printf("i = %d \n",i);
}
int main()
{
    SqList* sq; //野指针
    InitList(sq);
    ElemenType x[10] = { 3,8,2,7,1,5,3,4,6,0 };
    CreateList(sq, x, 10);
    DispList(sq);
    printf("\n");

    move1(sq);
    DispList(sq);
     /////////////////////////
    SqList* sq2; //野指针
    InitList(sq2);
    ElemenType y[10] = { 3,8,2,7,1,5,3,4,6,0 };
    CreateList(sq2, y, 10);
    DispList(sq2);
    printf("\n");

    move2(sq2);
    DispList(sq2);
    system("pause");
    return 0;
}
  • 单链表
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
#include <stdio.h>
#include <stdlib.h>

//typedef int ElemenType; //数据为其他类型,常见为符合类型
//城市表 区号--名字--说明
typedef struct
{
    char code[4];
    char name[16];
    char description[32];
}ElemType;

//线性表--单链表
typedef struct LNode
{
    ElemType  data; //数据域
    struct LNode* next ;//指针域,指向后续节点
}LinkList;

//***********头结点(数据域为空,指针域指向开始节点)
//***********终端节点(数据域为最后元素,指针域为NULL)
//***********存储密度 = 节点数据域占用空间 / 节点占用空间总量   ******************//
//存储密度越大,存储空间的利用率越高
//顺序表 的 存储密度为1,链表 的存储密度 取决于 数据域的大小

//插入节点    ---  修改前后节点 的指针指向。
//删除节点    ---  如果有中间局部变量指针,需要free(q)释放内存
//头插法建表  ---
//尾插法建表  ---


//头插法创建链表
void CreateListF(LinkList* &L,ElemType a[],int n)
{
    LinkList* s;
    int i;
    L = (LinkList*)malloc(sizeof(LinkList)); //分配头节点的空间
    L->next = NULL;

    //将数组a,分配到链表中
    for (i = 0; i < n; i++)
    {
        s = (LinkList*)malloc(sizeof(LinkList));
        s->data = a[i];
        s->next = L->next; //这两句顺序 不能颠倒。
        L->next = s;
    }
}
//尾茶法创建单链表 -- 增加一个尾指针
void CreateListR(LinkList* &L, ElemType a[], int n)
{
    LinkList* s; //为每个节点  分配空间
    LinkList* r; //尾指针
    int i; // n指代数组a的元素个数,以便于循环,防止溢出
    L = (LinkList*)malloc(sizeof(LinkList)); //创建头节点

    r = L;

    for (i = 0; i < n; i++)
    {
        s = (LinkList*)malloc(sizeof(LinkList));
        s->data = a[i];
        r->next = s;
        r = s;
    }
    r->next = NULL;
}
//销毁单链表  ---  **逐一**释放全部节点空间
void DestroyList(LinkList* &L)
{
    LinkList *pre = L, *p = L->next; //两个指针相随
    while (p != NULL)
    {
        free(pre);
        pre = p;
        p = pre->next;
    }
    free(pre); //释放最后一个元素
}
//判空
bool ListEmpty(LinkList* &L)
{
    return(L->next == NULL);
}
//返回单链表的长度  头结点不算(头结点不保存数据)
int ListLength(LinkList* &L)
{
    int n = 0;
    LinkList *p = L; //p指向头结点
    while (p->next != NULL)
    {
        n++;
        p = p->next;
    }
    return n;
}
//输出单链表
void DispList(LinkList* &L)
{
    LinkList *p = L->next;//首节点没有数据
    while (p != NULL)
    {
        printf("data is %s\n", p->data.code);
        p = p->next;
    }
    printf("_____\n");
}
//求线性表中指定位置的某个元素
bool GetElem(LinkList* &L, int i,ElemType& e)
{
    int j = 0;
    LinkList *p = L;
    while (j < i && p != NULL)
    {
        j++;
        p = p->next;
    }//用于定位到第i个元素
    if (p != NULL)
        return false;
    else
    {
        e = p->data;
        return true;
    }
}
//按元素值查找
int LocateElem(LinkList* &L, char e[])
{
    int i = 1;
    LinkList *p = L->next;
    while (p != NULL && ((p->data.code) != e))   //!= 需要操作符重载
    {
        p = p->next;
        i++;
    }
    if (p == NULL)
        return 0;
    else
        return i;
}
//指定位置  --  插入数据
bool ListInsert(LinkList* &L, int i, ElemType e)
{
    int j = 0;
    LinkList *p = L, *s;//s 指代要插入的元素,需要分配空间
    while (j < i - 1 && p != NULL)
    {
        j++;
        p = p->next; //定位到第i个元素
    }
    if (p == NULL)
        return false;
    else
    {
        s = (LinkList*)malloc(sizeof(LinkList));
        s->data = e;
        s->next = p->next;
        p->next = s;
        return true;
    }
}
//删除数据元素
bool ListDelete(LinkList* &L, int i, ElemType &e)
{
    int j = 0;
    LinkList* p = L, *q; //删除,所以需要两个指针跟随。
    while (j < i - 1 && p != NULL)
    {
        j++;
        p = p->next;
    }
    if (p == NULL)
        return false;
    else
    {
        q = p->next;
        if (q == NULL)
            return false;
        e = q->data;
        p->next = q->next;
        free(q);
        return true;
    }
}
int main()
{
    ElemType a[3] = { {"001","beijing","BJ"},{"021","shanghai","SH"},{"086","china","CH"} };
    LinkList *p,*q;
    CreateListF(p, a, 3);
    DispList(p);
    CreateListR(q, a, 3);
    DispList(q);
    system("pause");
    return 0;
}
  • 单链表 – 拆分
    这里写图片描述
    这里写图片描述
void split(LinkList* &L, LinkList* &L1, LinkList* &L2)
{
    LinkList *p = L->next, *q, *r1;
    L1 = L; //L1使用L的头结点
    r1 = L1;
    L2 = (LinkList*)malloc(sizeof(LinkList));//L2 自建头结点;
    L2->next = NULL; //尾插法

    while (p != NULL)
    {
        r1->next = p;// r1 代表了分离出来的第一条链
        r1 = p; //p 后移, r1 第一个元素
        p = p->next; // p第二个元素
        q = p->next;  //q p后面元素,第三个

        p->next = L2->next; //L2尾插法
        L2->next = p;
        p = q; // p 后移
    }
    r1->next = NULL;
}
  • 单链表 — 删除单链表中最大的节点
//删除单链表中元素最大的节点
//单链表只有单项,所以找到最大值得节点,还必须记住前向的节点
//比较大小需要一次比较最大值并保存,对于单链表还需要保存最大值之前的位置
void DelMaxNode(LinkList* &L)
{
    LinkList *p = L->next, *pre = L, *maxp = p, *maxpre = pre;
    while (p != NULL)
    {
        if (maxp->data.code < p->data.code)
        {
            maxp = p;
            maxpre = pre;
        }
        pre = p;
        p = p->next;
    }
    maxpre->next = maxp->next;
    free(maxp);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值