线性表 C

本文详细介绍了如何使用C语言实现经典的约瑟夫环问题,涵盖了数据结构线性表的应用,通过递归或循环来解决该问题。

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

#include<stdio.h>
#include<malloc.h>    //注意这个分配地址的头文件必须得加
#define INITIAL_SIZE 100   //定义线性表的初始大小
#define  INCREACEMENT 10    //定义线性表的分配增量


//定义一个线性表结构
struct List
{
    int *Elem;   //线性表的基址
int Length;   //当前长度
int Allocate_size;  //当前分配的容量
}*L;


//初始化线性表
void Init_List(List &L)
{

    L.Elem=(int *)malloc(INITIAL_SIZE* sizeof(int));   //分配基地址
if (!L.Elem ) return;   
L.Length =0;    //初始长度为0
L.Allocate_size =INITIAL_SIZE;  //初始分配的大小为100
}


//向线性表中插入一个数
void InsertInto_List(List &L,int i,int e)
{
int *p,*q;   
     if (i>L.Length+1 || i<1)return;    //先判断要插入的序号在不在线性表长度之内
if(L.Length>=L.Allocate_size)    //如果线性表的长度大于等于分配的大小时,需重新分配线性表大小
{
         int *newbase=(int *)realloc(L.Elem ,(L.Length +INCREACEMENT)*sizeof(int));
 if (!newbase)return;
 L.Elem =newbase;      //基地址改变
 L.Allocate_size +=INCREACEMENT;  //分配的大小加倍
}
          q=&(L.Elem [i-1]);   //要插入的位序
 for (p=&(L.Elem [L.Length-1]);p>=q;p--)    //循环实现要插入位置以后的数都要后移一位
 {
 *(p+1)=*p;
 }
 *q=e;   //给要插入的位序赋值要插入的值
 L.Length +=1;  //线性表加1

}




//删除线性表中一个数
void delete_List(List &L,int i,int &e)
{
int *p,*q;
    if (i<1||i>L.Length )return ;  //先判断要删除的位序的值是否在线性表中
else 
{
     p=&L.Elem [i-1];   //要删除的位序
        e=*p;     //将删除的数赋值给e
q=L.Elem +L.Length -1;   //线性表最后的位序
for (++p;p<=q;++p)*(p-1)=*p;   //循环实现删除位序后的数据前移一位
--L.Length ;   //线性表长度减一
}
}


//实现两个数相比较
bool compare(int a,int b)
{
if (a==b)return true;
else return false;
}


//查找一个数在线性表中的位序
int Locate_List(List &L,int e)
{
for (int i=1;i<L.Length;i++ )
{
    if (compare(e,L.Elem[i]))
return i;
}
return 0;
}


int main()
 {
//要插入的值
int InsertNum=89;   
int SeletNum=76;
int compareNum=76;


int returnValue;  //要返回的值

//注意要首先初始化L,因为一开始L是不指向任何地址的,
//只有malloc一个地址给他,L才指向一个有意义的地址,*L才能真正得到一个struct List,之后的所有对L的使用才有意义
   L=(List *)malloc(sizeof(struct List));  


Init_List(*L);   //初始化线性表


//插入数据
     InsertInto_List(*L,1,InsertNum);
InsertInto_List(*L,2,InsertNum);
InsertInto_List(*L,3,SeletNum);


delete_List(*L,2,returnValue);  //删除数据
     int Locate= Locate_List(*L,InsertNum);   //查找一个数在线性表中的位序 
 printf("%d 在线性表中的位序为: %d\n",compareNum,Locate);  //输出查找到的位序
 return 0;
 }

约瑟夫环

#include <stdio.h>
#include <malloc.h>

/*构建结构体*/
typedef struct Node{
    int Num;
    struct Node *next;
}JoseNode, *PNode, *HNode;

/**********初始化循环单链表*********/
int JoseInit(HNode *h)
{
    if (!h)
    {
        printf("初始化链表错误!\n");
        return 0;
    }
    (*h)->next = (*h);//循环单链表
    return 1;

}

/*************单链表插入操作**********/
int JoseInsert(JoseNode *h, int pos, int x)
{    
    PNode p=h,q;
    int i=1;
    if (pos == 1)/*尾插法*/
    {
        p->Num = x;
        p->next = p;
        return 1;
    }
    while(i<pos-1)
    {
        p=p->next;
        i++;
    }
    q=(PNode)malloc(sizeof(JoseNode));
    q->Num=x;
    q->next=p->next;
    p->next=q;
    return 1;
}

/*遍历*/
void TraverseList(HNode h, int M)
{
    int i = 0;
    PNode p = h;
    printf("参与的人的编号为:\n");
    while (i<M)
    {
        printf("%d\t", p->Num);
        p = p->next;
        i++;
    }
    printf("\n");
}
/**************出局函数****************/

int JoseDelete(HNode h, int M, int k)
{    int i;
    PNode p=h,q;
    while(M>1)
    {
        for(i=1;i<k-1;i++)
        {
            p=p->next;
        }

        q=p->next;
        p->next=q->next;
        printf("出局的人为:%d号\n",q->Num);
        free(q);

        p=p->next;
        M--;
    }
    printf("***************获胜者为:%d号***************",p->Num);
    return 1;
}


/***************************************/
int main()
{
    int i;//计数器
    int N;//参与的人数
    int k;//报数密码
    printf("请输入参与人数:");
    scanf("%d",&N);
    printf("请输入出局密码:");
    scanf("%d",&k);

/**************得到头结点****************/
    HNode h = ((HNode)malloc(sizeof(JoseNode)));

/***************初始化单链表************/
    JoseInit(&h);

/******将编号插入到循环单链表中******/
    for (i = 1; i <=N; i++)
    {
        JoseInsert(h, i, i);
    }
/**************遍历单链表***************/
    TraverseList(h,N);

/***************出局函数************/
    if(k > 1)
    JoseDelete(h, N, k);
    else
    {
        for(i = 1; i < N; i++)
            printf("出局的人为:%d号\n",i);
        printf("***************获胜者为:%d号***************",N);
    }

    printf("\n");
    printf("\n");
    return 0;
}
<think>好的,用户想了解线性表在C语言中的实现与操作。首先,我需要回忆线性表的基本概念。线性表是一种常见的数据结构,分为顺序表和链表两种实现方式。用户提供的引用资料提到了顺序表和单链表的实现,所以我需要分别解释这两种方法。 接下来,用户提到引用[1]和[2],其中引用[2]详细说明了顺序表的C语言实现步骤,包括结构体定义、初始化、插入、删除等操作。而引用[1]鼓励用两种方式实现,所以我也需要涵盖链表的实现。 用户的问题是关于C语言线性表的实现和操作,因此我的回答需要结构清晰,分步骤讲解。可能需要先介绍顺序表,包括结构体定义、初始化、插入、删除等操作的代码示例。然后转向链表,同样展示结构体定义和基本操作。 需要注意用户提到的要求,比如键盘输入整型数据创建线性表,以及各种操作的实现方法。因此,在代码示例中,应该包含如何从用户输入构建线性表,并演示插入、删除等操作。 同时,用户希望回答真实可靠,所以需要确保代码的正确性,比如在插入和删除操作时检查边界条件,避免内存泄漏(链表的情况下)。此外,引用标记要正确,每个参考的部分都要在末尾添加[^1]或[^2]。 可能还需要比较顺序表和链表的优缺点,帮助用户理解不同实现的应用场景。例如,顺序表适合随机访问,链表适合频繁插入删除。 最后,生成相关问题,可能涉及两种实现的比较、具体操作的时间复杂度,或者实际应用中的选择依据。确保问题与用户的学习需求相关,帮助他们进一步探索。 检查是否有遗漏,比如是否涵盖了创建、插入、删除、查找等基本操作,代码示例是否符合C语言标准,以及引用是否正确。确认无误后,整理回答结构,使其易于理解,逐步引导用户掌握线性表的实现。</think>### 线性表在C语言中的实现与操作 线性表是最基础的数据结构之一,在C语言中可通过顺序表(数组实现)和链表(指针实现)两种方式实现。以下分步骤说明其实现方法及核心操作。 --- #### 一、顺序表实现 顺序表通过数组存储元素,支持随机访问,但插入/删除需移动元素[^1]。 1. **结构体定义** 使用结构体封装数组和长度: ```c #define MAX_SIZE 100 typedef struct { int data[MAX_SIZE]; int length; } SqList; ``` 2. **初始化** 初始化空表: ```c void InitList(SqList *L) { L->length = 0; } ``` 3. **插入操作** 在位置`i`插入元素`e`: ```c int ListInsert(SqList *L, int i, int e) { if (i < 1 || i > L->length + 1 || L->length >= MAX_SIZE) return 0; // 越界或表满 for (int j = L->length; j >= i; j--) L->data[j] = L->data[j-1]; L->data[i-1] = e; L->length++; return 1; } ``` 4. **删除操作** 删除位置`i`的元素: ```c int ListDelete(SqList *L, int i, int *e) { if (i < 1 || i > L->length) return 0; *e = L->data[i-1]; for (int j = i; j < L->length; j++) L->data[j-1] = L->data[j]; L->length--; return 1; } ``` --- #### 二、链表实现 链表通过指针动态分配内存,插入/删除高效但访问需遍历。 1. **结点定义** 单链表结点结构: ```c typedef struct LNode { int data; struct LNode *next; } LNode, *LinkList; ``` 2. **头插法创建链表** 从键盘输入数据创建链表: ```c LinkList CreateListHead() { LinkList L = (LinkList)malloc(sizeof(LNode)); L->next = NULL; int num; printf("输入元素(-1结束):"); while (scanf("%d", &num), num != -1) { LNode *p = (LNode*)malloc(sizeof(LNode)); p->data = num; p->next = L->next; L->next = p; } return L; } ``` 3. **插入操作** 在位置`i`插入元素: ```c int ListInsert(LinkList L, int i, int e) { LNode *p = L; int j = 0; while (p && j < i-1) { // 寻找第i-1个结点 p = p->next; j++; } if (!p || j > i-1) return 0; LNode *s = (LNode*)malloc(sizeof(LNode)); s->data = e; s->next = p->next; p->next = s; return 1; } ``` 4. **删除操作** 删除位置`i`的元素: ```c int ListDelete(LinkList L, int i, int *e) { LNode *p = L; int j = 0; while (p->next && j < i-1) { p = p->next; j++; } if (!(p->next) || j > i-1) return 0; LNode *q = p->next; *e = q->data; p->next = q->next; free(q); return 1; } ``` --- #### 三、对比与应用场景 | 特性 | 顺序表 | 链表 | |--------------|--------------------------|-------------------------| | 存储方式 | 连续内存 | 动态内存分配 | | 访问效率 | $O(1)$随机访问 | $O(n)$顺序访问 | | 插入/删除 | $O(n)$(需移动元素) | $O(1)$(已知位置) | | 适用场景 | 频繁查询、固定大小数据 | 频繁插入删除、动态扩展 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值