1、有n个整数,使其前面各数顺序向后移m个位置,最后m个数变成最前面的m个数。(该题是昨天"C语言编程练习day14"的第二题,用两个数组来完成,今天用链表来做,思路更简单)
输入:10 4 (n个整数,前面各数顺序向后移m个位置)
0 1 2 3 4 5 6 7 8 9
输出:
优化目标:无
思路:
调整结点链接的函数
/*
*改变结点链接
*@list:链表指针
*@m:要调整的最后m个元素
*/
void Change_ListLink(LinkList* list, int m){
if(list == NULL || m < 0 || m > list->size){
return;
}
//找到修改位置list->size - m,链接到头结点后面
LinkNode* pCurrent = &(list->head);
for(int i=0; i<=list->size - m; i++){
pCurrent = pCurrent->next;
}
//找到链尾位置,把第一个数据元素链接到链尾
LinkNode* pNext = &(list->head);
for(int i=0; i<list->size; i++){
pNext = pNext->next;
}
//修改位置
pNext->next = list->head.next;
list->head.next = pCurrent;
}
完整代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 1024
//链表结点
typedef struct LINKNODE{
struct LINKNODE* next;
}LinkNode;
//链表
typedef struct LINKLIST{
LinkNode head;
int size;
}LinkList;
//自定义数据
typedef struct MYDATA{
LinkNode data;
int value;
}MyData;
//初始化和链表
LinkList* Init_LinkList(){
LinkList* list = (LinkList*)malloc(sizeof(LinkList));
list->head.next = NULL;
list->size = 0;
return list;
}
/*
*插入结点
*@list:链表指针
*@data:插入的数据
*/
void Insert_LinkList(LinkList* list, LinkNode* data){
//判断参数的合法性
if(list == NULL || data == NULL){
return;
}
//找到插入位置,链尾
LinkNode* pCurrent = &(list->head);
for(int i=0; i<list->size; i++){
pCurrent = pCurrent->next;
}
//插入结点,尾插
data->next = pCurrent->next;
pCurrent->next = data;
list->size++;
}
/*
*改变结点链接
*@list:链表指针
*@m:要调整的最后m个元素
*/
void Change_ListLink(LinkList* list, int m){
if(list == NULL || m < 0 || m > list->size){
return;
}
//找到修改位置list->size - m,链接到头结点后面
LinkNode* pCurrent = &(list->head);
for(int i=0; i<=list->size - m; i++){
pCurrent = pCurrent->next;
}
//找到链尾位置,把第一个数据元素链接到链尾
LinkNode* pNext = &(list->head);
for(int i=0; i<list->size; i++){
pNext = pNext->next;
}
//修改位置
pNext->next = list->head.next;
list->head.next = pCurrent;
}
/*
*打印
*@list:链表指针
*/
void MyPrint(LinkList* list){
LinkNode* pNext = list->head.next;
for(int i=0; i<list->size; i++){
MyData* data = (MyData*)pNext;
printf("%d ", data->value);
pNext = pNext->next;
}
}
/*
*链表销毁
*@list:链表指针
*/
void FreeSpace_LinkList(LinkList* list){
//判断参数的合法性
if(list == NULL){
return;
}
free(list);
}
int main(){
int n, m;
scanf("%d%d", &n, &m);
MyData num[MAX_SIZE];
//初始化链表
LinkList* list = Init_LinkList();
for(int i=0; i<n; i++){
//输入n个要调整的数
scanf("%d", &num[i].value);
//插入数据
Insert_LinkList(list, (LinkNode*)&num[i]);
}
//打印数据,修改位置前
MyPrint(list);
//修改位置
Change_ListLink(list, m);
printf("\n");
//打印数据,修改位置后
MyPrint(list);
//释放空间
FreeSpace_LinkList(list);
return 0;
}
2、输入一个整数,输出每个数字对应的拼音。当整数为负数时,先输出fu字。十个数字对应的拼音如下:
输入:输入在一行中给出一个整数,如:1234。
输出:在一行中输出这个整数对应的拼音,每个数字的拼音之间用空格分开,行末没有最后的空格。如 yi er san si。
优化目标:无
```c
#include <stdio.h>
#include <string.h>
#define MAX 1024
/*
*打印结果函数
*@n:需要读的数
*@num:存放n取出的每一位
*/
void test(int n, int* num){
int i = 0;
while(n > 0){
int k = n % 10;
num[i] = k;
i++;
n = n / 10;
}
for(int j=i-1; j>=0; j--){
if(num[j] == 0){
printf("ling");
}else if(num[j] == 1){
printf("yi");
}else if(num[j] == 2){
printf("er");
}else if(num[j] == 3){
printf("san");
}else if(num[j] == 4){
printf("si");
}else if(num[j] == 5){
printf("wu");
}else if(num[j] == 6){
printf("liu");
}else if(num[j] == 7){
printf("qi");
}else if(num[j] == 8){
printf("ba");
}else if(num[j] == 9){
printf("jiu");
}
if(j != 0){
printf(" ");
}
}
}
int main(){
int N;
scanf("%d", &N);
int num[MAX];
if(N > 0){
test(N, num);
}else if(N < 0){
N = -N;
printf("%s ", "fu");
test(N, num);
}else{
printf("%s", "ling");
}
return 0;
}
3、你的程序要读入一行文本,其中以空格分隔为若干个单词,以.结束。你要输出每个单词的长度。这里的单词与语言无关,可以包括各种符号,比如it’s算一个单词,长度为4。注意,行中可能出现连续的空格;最后的.不计算在内。
输入:输入在一行中给出一行文本,以.结束。样例:It’s great to see you here.
输出:在一行中输出这行文本对应的单词的长度,每个长度之间以空格隔开,行 末没有最后的空格。样例:4 5 2 3 3 4
优化目标:无
#include <stdio.h>
#include <string.h>
#define MAX 1024
int main(){
char str[MAX];
gets(str);
int count=0;
int j=0, i=0;
int num[MAX] = {0};
while(str[i] != '\0'){
if(str[i] == ' ' || str[i] == '.'){
if(count > 0){
num[j] = count;
j++;
count = 0;
}
}else{
count++;
}
i++;
}
if(j>0){//屏蔽掉输入为"空句子"这种特殊情况
for(int k=0; k<j-1; k++){
if(num[k] != 0){
printf("%d ", num[k]);
}
}
printf("%d",num[j-1]);
}
return 0;
}
4、队列的顺序存储
队列是一种先进先出(First In First Out,FIFO)的数据结构。队列只能在队尾插入元素,在队首删除元素。队列被用在很对地方,比如提交操作系统执行的一系列进程、打印任务池等。
4.1实现队列孙秀存储相关API的声明。创建头文件SeqQueue.h来声明相关函数。
#ifndef SEQQUEUE_H
#define SEQQUEUE_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 024
typedef struct SEQQUEUE {
void* data[MAX_SIZE];
int size;
}SeqQueue;
//初始化队
SeqQueue* Init_SeqQueue();
//入队
void Push_SeqQueu(SeqQueue* queue, void* data);
//返回队头元素
void* Front_SeqQueu(SeqQueue* queue);
//出队
void Pop_SeqQueu(SeqQueue* queue);
//返回队尾元素
void* Back_SeqQueu(SeqQueue* queue);
//返回队列大小
int Size_SeqQueu(SeqQueue* queue);
//清空队
void Clear_SeqQueu(SeqQueue* queue);
//销毁队
void FreeSpace_SeqQueu(SeqQueue* queue);
#endif // !SEQQUEUE_H
4.2实现队列顺序存储相关API的定义。创建c文件SeqQueue.c来定义相关函数。
#include "SeqQueue.h"
/*
*初始化队
*/
SeqQueue* Init_SeqQueue() {
SeqQueue* queue = (SeqQueue*)malloc(sizeof(SeqQueue));
for (int i = 0; i < MAX_SIZE; i++) {
queue->data[i] = NULL;
}
queue->size = 0;
return queue;
}
/*
*入队,数组模拟队,用数组的左边做队头
*@queue:队列指针
*@data:入队的数据
*/
void Push_SeqQueu(SeqQueue* queue, void* data) {
//判断参数的合法性
if (queue == NULL || data == NULL) {
return;
}
//如果入队时,队列已经满了,则直接返回
if (queue->size == MAX_SIZE) {
return;
}
//入队,因为队的特定是先进先出,队头入,队尾出
queue->data[queue->size] = data;
queue->size++;
}
/*
*返回队头元素
*@queue:队列指针
*/
void* Front_SeqQueu(SeqQueue* queue) {
//判断参数的合法性
if (queue == NULL) {
return NULL;
}
//如果队空,则返回空
if(queue->size == 0){
return NULL;
}
return queue->data[0];
}
/*
*出队
*@queue:队列指针
*/
void Pop_SeqQueu(SeqQueue* queue) {
//判断参数的合法性
if (queue == NULL) {
return;
}
//如果队空,则返回空
if (queue->size == 0) {
return;
}
for (int i = 0; i < queue->size - 1; i++) {
queue->data[i] = queue->data[i + 1];
}
queue->size--;
}
/*
*返回队尾元素
*@queue:队列指针
*/
void* Back_SeqQueu(SeqQueue* queue) {
//判断参数的合法性
if (queue == NULL) {
return NULL;
}
//如果队空,则返回空
if (queue->size == 0) {
return NULL;
}
return queue->data[queue->size - 1];
}
/*
*返回队列大小
*@queue:队列指针
*/
int Size_SeqQueu(SeqQueue* queue) {
//判断参数的合法性
if (queue == NULL) {
return -1;
}
return queue->size;
}
/*
*返清空队
*@queue:队列指针
*/
void Clear_SeqQueu(SeqQueue* queue) {
//判断参数的合法性
if (queue == NULL) {
return;
}
for (int i = 0; i < queue->size; i++) {
queue->data[i] = NULL;
}
queue->size = 0;
}
/*
*销毁队
*@queue:队列指针
*/
void FreeSpace_SeqQueu(SeqQueue* queue) {
//判断参数的合法性
if (queue == NULL) {
return;
}
free(queue);
}
4.3函数测试。队列的顺序存储.c文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SeqQueue.h"
typedef struct PERSON {
char name[64];
int age;
}Person;
int main() {
//初始化队列
SeqQueue* queue = Init_SeqQueue();
//初始化队列
Person p1 = { "aaa", 10 };
Person p2 = { "bbb", 20 };
Person p3 = { "ccc", 30 };
Person p4 = { "ddd", 40 };
Person p5 = { "eee", 50 };
//入队
Push_SeqQueu(queue, &p1);
Push_SeqQueu(queue, &p2);
Push_SeqQueu(queue, &p3);
Push_SeqQueu(queue, &p4);
Push_SeqQueu(queue, &p5);
//打印数据
while (Size_SeqQueu(queue) > 0) {
Person* p = (Person*)Front_SeqQueu(queue);
printf("Name:%s, Age:%d\n", p->name, p->age);
Pop_SeqQueu(queue);
}
//释放内存
FreeSpace_SeqQueu(queue);
return 0;
}
总结:今天用链表把昨天的第二题写了一下,用链表看似代码较之前的方法多一些,但逻辑却非常清晰。此外,通过这一次的链表解题,自己对链表的操作更加熟练了。同时,自己可以通过链表来解决一些问题了,而不是在学习链表时仅仅写一些给到的例子。