# C语言---数据结构实验---顺序表的合并---链表的基本操作---重点解析约瑟夫问题

10 篇文章 2 订阅

## 顺序表的合并

### 代码实现

//建立有序表：12，23，46，67，85
//建立有序表：5，59，94
//两个有序顺序表合并为一个有序顺序表，验证代码的正确性。

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int SLDataType;
typedef struct SeqList
{
SLDataType* a;
int size;
int capacity;
}SeqList;

void SListInit(SeqList* ps)
{
//assert(ps);
ps->size = 0;
ps->capacity = 4;
ps->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);
if (ps->a == NULL)
{
perror("malloc fail");
return;
}
}

void SListDestroy(SeqList* ps)
{
assert(ps);
ps->a = NULL;
ps->capacity = 0;
ps->size = 0;
}

void SListCheckCapacity(SeqList* ps)
{
assert(ps);
if (ps->size == ps->capacity)
{
SLDataType* tmp = NULL;
tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * (ps->capacity) * 2);
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->a = tmp;
ps->capacity *= 2;
//printf("The capacity now:%d\n", ps->capacity);
}
else
{
return;
}
}

void SListPushBack(SeqList* ps, SLDataType x)
{
assert(ps);
SListCheckCapacity(ps);
ps->a[ps->size] = x;
ps->size++;
}

void SListPrint(SeqList* ps)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}

void SListMerge(SeqList* ps1, SeqList* ps2)
{
assert(ps1);
assert(ps2);
SeqList ps;
SListInit(&ps);
int cur1 = 0, cur2 = 0;
while (cur1 < ps1->size && cur2 < ps2->size)
{
if (ps1->a[cur1] <= ps2->a[cur2])
{
SListPushBack(&ps, ps1->a[cur1]);
cur1++;
}
else
{
SListPushBack(&ps, ps2->a[cur2]);
cur2++;
}
}
while (cur1 < ps1->size)
{
SListPushBack(&ps, ps1->a[cur1]);
cur1++;
}
while (cur2 < ps2->size)
{
SListPushBack(&ps, ps2->a[cur2]);
cur2++;
}
printf("The result of merging two seqlists is:\n");
SListPrint(&ps);
}

int main()
{
SeqList ps1;
SeqList ps2;
SListInit(&ps1);
SListInit(&ps2);
int quantity1 = 0, quantity2 = 0, input = 0;

printf("Input quantity of seqlist1-> ");
scanf("%d", &quantity1);
for (int i = 0; i < quantity1; i++)
{
scanf("%d", &input);
SListPushBack(&ps1, input);
}

printf("Input quantity of seqlist2-> ");
scanf("%d", &quantity2);
for (int i = 0; i < quantity2; i++)
{
scanf("%d", &input);
SListPushBack(&ps2, input);
}

SListMerge(&ps1, &ps2);
return 0;
}


Gitee下载链接

## 链表的基本操作

1.通讯者的结点类型定义如下：
typedef struct {
char num[5] ; //编号
char name[9] ; //姓名
char sex[3] ; //性别
char phone[13]; //电话
char addr[31] ; //地址
]DataType ;
2.线性表的链式存储结构定义如下：
typedef struct node { //结点类型定义
DataType data ; //结点数据域
struct node * next ; //结点指针域
} ListNode ;
typedef ListNode * LinkList ;
ListNode * p ; //定义一个指向结点的指针变量
LinkList head ; //定义指向单链表的头指针
3.主控菜单设计要求

1. 通讯录链表的建立
2. 通讯者结点的插入
3. 通讯者结点的查询
4. 通讯者结点的删除
5. 通讯录链表的输出
6. 退出管理系统
请选择 0——5
使用数字0——5来选择菜单项，其他输入则不起作用。

1.利用单向循环链表存储结构模拟此过程，按照出列的顺序输出各人的编号。
2.为了不失一般性，将30改为一个任意输入的正整数n，而报数上限（原为9）也为一个任选的正整数k。这样该算法描述如下：
（1）创建含有n个结点的单循环链表；
（2）生者与死者的选择：
p指向链表第一个结点，初始i 置为1；
while (i<=n/2) //删除一半的结点
{ 从p指向的结点沿链前进k-1步；

i自增1；
}
（3）输出所有生者的位置。

3.测试结果

### 代码实现

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdbool.h>

typedef  struct
{
char  num[5];    //编号
char  name[9];   //姓名
char  sex[3];     //性别
char  phone[13];  //电话
char  addr[31];   //地址
}DataType;

typedef struct node
{
DataType data;
struct node* next;
}ListNode;

//头节点用head
//定义一个指向结点的指针变量 ListNode* p;

ListNode* BuyListNode(DataType x);

void ListNodePush(ListNode** phead);

DataType Buynewdata();

void ListNodePrint(ListNode** phead);

int ListNodeFind(ListNode* head, const char* Findname);

void ListNodePop(ListNode** phead, const char* Popname);

ListNode* BuyListNode(DataType x)
{
ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
if (newnode == NULL)
{
perror("malloc fail");
return NULL;
}
newnode->next = NULL;
newnode->data = x;
return newnode;
}

DataType Buynewdata()
{
DataType newdata;
printf("请依次输入编号 姓名 性别 电话 地址\n");
scanf("%s %s %s %s %s",
newdata.num, newdata.name, newdata.sex, newdata.phone, newdata.addr);
return  newdata;
}

void ListNodePush(ListNode** phead)
{
assert(phead);
ListNode* newnode = BuyListNode(Buynewdata());
if (*phead == NULL)
{
*phead = newnode;
}
else
{
newnode->next = *phead;
*phead = newnode;
}
}

void ListNodePrint(ListNode** phead)
{
ListNode* cur = *phead;
printf("%-5s%-10s%-8s%-13s%-31s\n",
"编号", "姓名", "性别", "电话", "地址");
while (cur)
{
printf("%-5s%-10s%-8s%-13s%-31s\n",
cur->data.num, cur->data.name, cur->data.sex,
cur->data.phone, cur->data.addr);
cur = cur->next;
}
}

int ListNodeFind(ListNode* head, const char* Findname)
{
ListNode* cur = head;
while (cur)
{
if (strcmp(Findname, cur->data.name) == 0)
{
printf("找到了,该人的信息如下\n");
printf("%-5s%-10s%-8s%-13s%-31s\n",
"编号", "姓名", "性别", "电话", "地址");
printf("%-5s%-10s%-8s%-13s%-31s\n",
cur->data.num, cur->data.name, cur->data.sex,
cur->data.phone, cur->data.addr);
return 1;
}
else
{
cur = cur->next;
}
}
printf("找不到信息\n");
return 0;
}

void ListNodePop(ListNode** phead, const char* Popname)
{
assert(*phead);
assert(phead);
if (ListNodeFind(*phead, Popname))
{
ListNode* Findnode = *phead;
ListNode* prev = *phead;
while (strcmp(Findnode->data.name, Popname) != 0)
{
prev = Findnode;
Findnode = Findnode->next;
}
prev->next = Findnode->next;
free(Findnode);
Findnode = NULL;
printf("删除该人信息成功\n");
return;
}
else
{
printf("找不到该人信息\n");
return;
}
}

void menu()
{
printf("*********************************************\n");
printf("****1.建立信息表************** 2.插入信息 ****\n");
printf("****3.查询信息  ************** 4.删除信息 ****\n");
printf("****5.打印信息  ************** 0.退出     ****\n");
printf("*********************************************\n");
}

void SetupListNode(ListNode** phead)
{
int num = 0;
printf("建立链表成功，开始录入信息\n");
printf("输入要录取信息的个数->");
scanf("%d", &num);
while (num--)
{
ListNodePush(phead);
}
}

void FindFunction(ListNode* head)
{
char Findname[20] = { 0 };
printf("输入要查找的人名");
scanf("%s", Findname);
ListNodeFind(head, Findname);
}

void PopFunction(ListNode** phead)
{
char Popname[20] = { 0 };
printf("输入要查找的人名");
scanf("%s", Popname);
ListNodePop(phead, Popname);
}

int main()
{
menu();
int input = 0;
ListNode* head = NULL;
do
{
printf("请选择->");
scanf("%d", &input);
switch (input)
{
case 1:
SetupListNode(&head);
break;
case 2:
if (head == NULL)
{
printf("通讯录还未建立，请先建立\n");
break;
}
else
{
ListNodePush(&head);
break;
}
case 3:
if (head == NULL)
{
printf("通讯录还未建立，请先建立\n");
break;
}
else
{
FindFunction(head);
break;
}
case 4:
if (head == NULL)
{
printf("通讯录还未建立，请先建立\n");
break;
}
else
{
PopFunction(&head);
break;
}
case 5:
if (head == NULL)
{
printf("通讯录还未建立，请先建立\n");
break;
}
else
{
ListNodePrint(&head);
break;
}
case 0:
break;
default:
printf("请重新选择\n");
break;
}
menu();
} while (input);
return 0;
}


Gitee下载链接

## 约瑟夫问题

### 问题分析

1. 利用单向循环链表存储结构模拟此过程，按照出列的顺序输出各人的编号。
2. 为了不失一般性，将30改为一个任意输入的正整数n，而报数上限（原为9）也为一个任选的正整数k。这样该算法描述如下：
（1） 创建含有n个结点的单循环链表；

（2） 生者与死者的选择：

p指向链表第一个结点，初始i 置为1；

while (i<=n/2)   //删除一半的结点

{

p指向q的下一个结点；

i自增1；
}

（3） 输出所有生者的位置。

1. 测试结果
对于总人数30，报数上限为9，则
死者编号为：9，18，27，6，16，26，7，19，30，12，24，8，22，5，23
生者编号为：1，2，3，4，10，11，13，14，15，17，20，21，25，28，29

1. 要解决循环链表问题

2. 要解决如何找到要删元素的问题

### 代码实现

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

typedef int LTDataType;
typedef struct ListNode
{
LTDataType data;
struct ListNode* next;
}ListNode;

void ListNodePush(ListNode** phead,LTDataType x)
{
assert(phead);
ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
if (newnode == NULL)
{
perror("malloc fail");
return;
}
newnode->data = x;
newnode->next = NULL;

if (*phead == NULL)
{
*phead = newnode;
newnode->next = newnode;
}
else
{
ListNode* tail = *phead;
while (tail->next != *phead)
{
tail = tail->next;
}
newnode->next = *phead;
*phead = newnode;
tail->next = *phead;
}
}

void ListNodePop(ListNode** phead,ListNode* cur)
{
ListNode* prev = *phead;
ListNode* next = *phead;
while (prev->next != cur)
{
prev = prev->next;
}
next = cur->next;
prev->next = next;
//free(cur);
//cur = NULL;
}

void ListNodePrint(ListNode* head)
{
assert(head);
ListNode* cur = head->next;
printf("%d->", head->data);
while (cur!=head)
{
printf("%d->", cur->data);
cur = cur->next;
}
}

int main()
{
ListNode* plist = NULL;
for (int i = 30; i > 0; i--)
{
ListNodePush(&plist, i);
}
int a = 15;
ListNode* cur = plist;
while (a--)
{
for (int i = 0; i < 8; i++)
{
cur = cur->next;
}
ListNodePop(&plist, cur);
cur = cur->next;
}
ListNodePrint(plist);
return 0;
}

• 46
点赞
• 64
收藏
觉得还不错? 一键收藏
• 打赏
• 39
评论
12-27 3128
10-06 863
04-08 3035
03-09 276
10-08 3581
08-12 372
04-01
05-15 1585

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

¥1 ¥2 ¥4 ¥6 ¥10 ¥20

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