结构体

声明结构体变量的四种方式

1.先定义结构体,再声明结构体变量

struct student{
  long number;
  char name[20];
  char sex;
  float score;
};//先定义结构体
struct student s1,s2;//声明结构体变量

2.在定义结构体类型的同时声明结构变量

struct student{
  long number;
  char name[20];
  char sex;
  float score;
}s1,s2;//在定义结构体的同时定义结构体变量

3.直接声明结构体变量

struct{//省去结构体名
  long number;
  char name[20];
  char sex;
  float score;
}s1,s2;//直接给出结构体变量

此方法因为没有给出结构体名,所以不能用来在后面程序中声明此结构体类型的变量,因此在实际编程是这种方法用的较少。

4.typedef引用别名来定义

typedef struct student STUDENT; //给结构体student定义别名
struct student{
  long number;
  char name[20];
  char sex;
  float score;
};
STUDENT s1,s2;//使用别名STUDENT定义结构体

头歌作业

1.从键盘输入两个学生的学号,姓名和成绩(整数),分别存入结构体中,输出成绩较高的学生的学号,姓名和成绩。

#include <stdio.h>

typedef struct student STUDENT; 

struct student {
long number;
char name[20];
int score;
};

STUDENT s1, s2;

int main() {
    scanf("%ld %s %d", &s1.number, s1.name, &s1.score);
    scanf("%ld %s %d", &s2.number, s2.name, &s2.score);
    
if (s1.score > s2.score) {
	printf("%ld %s %d", s1.number, s1.name, s1.score);
} else {
	printf("%ld %s %d", s2.number, s2.name, s2.score);
}

return 0;
}

2.有 n 个学生的信息(包括学号,姓名,成绩),要求按照成绩的高低顺序输出学生的信息。

#include <stdio.h>
#include<stdlib.h>
// 定义学生结构体
typedef struct {
int student_id;
char name[50];
int score;
} Student;

// 按成绩降序比较函数
int compare(const void *a, const void *b) {
    Student *student_a = (Student *)a;
    Student *student_b = (Student *)b;
    if (student_a->score < student_b->score) {
    return 1;  
    } else if (student_a->score > student_b->score) {
    return -1;
    } else {
    return 0;  // 如果a的成绩等于b的成绩,返回0,表示a与b的顺序不变
    }
    }

int main() {
    int n;
    scanf("%d", &n);
    Student students[n];
    for (int i = 0; i < n; i++) 
    	scanf("%d%s%d", &students[i].student_id, students[i].name, &students[i].score);
    
    // C库快速排序函数 
    	qsort(students, n, sizeof(Student), compare);
    //指向待排序数组的起始地址。
    //n:数组中元素的个数。
    //size:数组中每个元素的大小。
    //compare:比较函数的指针,用于确定元素之间的顺序关系。
    
    for (int i = 0; i < n; i++) 
    	printf("%d %s %d\n", students[i].student_id, students[i].name, students[i].score);
    return 0;
}

用冒泡排序模拟实现qsort函数

冒泡函数基本写法

void BubbleSort(int* arr, int sz)
{
	int i = 0;
	int j = 0;
	//共进行sz-1趟
	for (i = 0; i < sz-1; i++)
	{
		int flag = 1;//每一趟进来都假设有序
// 每一趟
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				flag = 0;
			}
		}
//若falg还是1,说明没有交换->已经有序了break退出
		if (flag == 1)
		{
			break;
		}
	}
}
int main()
{
	int arr[10] = { 2,3,6,7,9,0,0,3,2,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	BubbleSort(arr, sz);
	return 0;
}

qsort库函数使用的是什么参数,我们设计的函数就使用什么参数!

//交换 --一个字节一个字节的交换,共交换width次
void Swap(char* buf1, char* buf2, size_t width)
{
	size_t i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}
void my_BubbleSort(void* base, size_t num,size_t width, int(*cmp)(const void* e1, const void* e2))
{
	//冒泡排序
	//若要排序n个元素,只需要进行n-1趟
	//每一趟可以少比较一个元素,每一趟可以使一个元素在确定的位置上
	//num:要排序元素的个数 类型是size_t 
//num是无符号数 防止产生警告 所以i和j也定义为size_t
// size_t == unsigned int 
	size_t i = 0;
	size_t j = 0;
 
	//共进行num-1趟
	for (i = 0; i < num; i++)
	{
		//每一趟
		for (j = 0; j < num - 1 - i; j++)
		{
			//比较
			//传地址   
			//相邻两个元素比较   width:宽度,每个元素所占字节
			//排成升序
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				//交换两数
				Swap( (char*)base + j * width, (char*)base + (j + 1) * width, width );
			}
		}
	}
}

1.为何将base强制类型转化为char*型指针:

原因:char* 指针+1跳过一个字节,+width:跳过width个字节,指向下一个元素。转化为其他类型不合适

2.交换函数:还要把宽度(每个元素所占字节数)传过去
因为交换的时候是传地址,所以要知道元素的宽度,一个字节一个字节的交换 ,这样也证明了使用char*指针的好处!

3.(char)base + j * width, (char)base + (j + 1) * width,

当j = 0时:比较的是第一个元素和第二个元素

j = 1时,比较的是第二个元素和第三个元素

.... 很妙的写法

3.有三个候选人,每个选民只能投一票,写一程序,用结构体存储数据,求出得票结果。三个候选人为 "Li", "Zhang","Sun"。

#include <stdio.h>
#include<string.h> 
typedef struct{
	char name[20];	
}student;
int main() {
    int n,a=0,b=0,c=0;
    scanf("%d", &n);
    student students[n];
    for (int i = 0; i < n; i++) 
    	scanf("%s", &students[i].name);
    for (int i = 0; i < n; i++){
    	if(strcmp(students[i].name,"Li")==0)
    		a++;
    		if(strcmp(students[i].name,"Zhang")==0)
    			b++;
    		if(strcmp(students[i].name,"Sun")==0)
    			c++;	
    	}
    	printf("Li:%d\nZhang:%d\nSun:%d",a,b,c);
    return 0;
}

4.使用结构体储存学生信息(包括学号,姓名,3 门课程成绩,总分),要求实现对学生信息修改和删除操作,最多50名学生。

#include <stdio.h>
#include <string.h>

int Count;
struct student {
char sno[20], name[20];
int math, english, chinese, sum;
};

void print(struct student stu) {
	printf("%s %s %d %d %d %d\n", stu.sno, stu.name, stu.math, stu.english, stu.chinese, stu.sum);
}

void query_stu(struct student s[], char *name) {
	for (int i = 0; i < Count; i++) {
		if (strcmp(s[i].name, name) == 0) {
		    print(s[i]);
		    }
	    }
   }

void delete_stu(struct student s[], char *sno) {
    int index = -1;
    for (int i = 0; i < Count; i++) {
    	if (strcmp(s[i].sno, sno) == 0) {
	    index = i;//mark
	    break;
	    }
    }
    if (index != -1) {
    	for (int i = index; i < Count - 1; i++) {
   			 s[i] = s[i + 1];
    	}
    Count--;//shan
    
    } 
}

void update_stu(struct student s[], char *sno, int math, int english, int chinese) {
    int index = -1;
    for (int i = 0; i < Count; i++) {
	    if (strcmp(s[i].sno, sno) == 0) {
	    index = i;//mark
	    break;
    }
}
if (index != -1) {
    s[index].math = math;
    s[index].english = english;
    s[index].chinese = chinese;
    s[index].sum = math + english + chinese;
    
	} 
}

int main(void) {
    int n, q;
    struct student students[50];
    scanf("%d%d", &n, &q);
    Count = n;
    
    for (int i = 0; i < n; i++) {
    	scanf("%s%s%d%d%d", students[i].sno, students[i].name, &students[i].math, &students[i].english, &students[i].chinese);
    	
		students[i].sum = students[i].math + students[i].english + students[i].chinese;
    }
    
    while (q--) {
	    int op;
	    scanf("%d", &op);
	    char sno[20], name[20];
		    if (op == 1) {
		    scanf("%s", name);
		    query_stu(students, name);//sousuo
		} 
		else if (op == 2) {
		    int a, b, c;
		    scanf("%s%d%d%d", sno, &a, &b, &c);
		    update_stu(students, sno, a, b, c);//gengxin
	    for (int i = 0; i < Count; i++)
	    print(students[i]);
		} 
		else {
		    scanf("%s", sno);
		    delete_stu(students, sno);//shanchu
		    for (int i = 0; i < Count; i++)
		    print(students[i]);
		    }
    }
    return 0;
}

链表

链表的建立
在链表建立过程中,首先要建立第一个结点,然后不断地在其尾部增加新结点,直到不需再有新结点,即尾指针指向NULL为止。

设有结构指针变量。

struct note p,p1,*head;

head:用来标志链表头;

p:在链表建立过程中,p总是不断先接受系统动态分配的新结点地址。

p1->next:存储新结点的地址。

头歌作业

1.建立单向链表

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

typedef struct node
{
int data;
struct node* next;
} Node;

Node* CreateList(int data)
{
    Node* phead = (Node*)malloc(sizeof(Node));
    phead->data = data;
    phead->next = NULL;
    return phead;
}

void InsertNode(Node* phead, int data)
{
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = NULL;
    
    Node* cur = phead;
    while (cur->next != NULL)
    {
    cur = cur->next;
    }
    cur->next = newNode;
    }
    
    void ShowList(Node* phead)
    {
    Node* cur = phead;
    while (cur != NULL)
    {
    printf("%d ", cur->data);
    cur = cur->next;
    }
    printf("\n");
}

int main(void)
{
    int n;
    scanf("%d", &n);
    
    int data;
    scanf("%d", &data);
    Node* phead = CreateList(data);
    
    int i;
    for (i = 1; i < n; i++)
    {
    scanf("%d", &data);
    InsertNode(phead, data);
    }
    
    ShowList(phead);
    
    return 0;
}  

2.统计单链表中的节点数

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

typedef struct node
{
int data;
struct node* next;
} Node;

Node* CreateList(int data)
{
    Node* phead = (Node*)malloc(sizeof(Node));
    phead->data = data;
    phead->next = NULL;
    return phead;
}

void InsertNode(Node* phead, int data)
{
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = NULL;
    
    Node* cur = phead;
    while (cur->next != NULL)
    {
    cur = cur->next;
    }
    cur->next = newNode;
}

void ShowList(Node* phead)
{
    Node* cur = phead;
    while (cur != NULL)
    {
    printf("%d ", cur->data);
    cur = cur->next;
    }
    printf("\n");
}

int CountNodes(Node* phead)
{
    int count = 0;
    Node* cur = phead;
    while (cur != NULL)
    {
    count++;
    cur = cur->next;
    }
    return count;
}

int main(void)
{
    int n;
    scanf("%d", &n);
    
    int data;
    scanf("%d", &data);
    Node* phead = CreateList(data);
    
    int i;
    for (i = 1; i < n; i++)
    {
    scanf("%d", &data);
    InsertNode(phead, data);
    }
    
    ShowList(phead);
    
    int nodeCount = CountNodes(phead);
    printf("%d\n", nodeCount);
    
    return 0;
}

单链表的逆置。

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

typedef struct node
{
int data;
struct node* next;
} Node;

Node* CreateList(int data)
{
    Node* phead = (Node*)malloc(sizeof(Node));
    phead->data = data;
    phead->next = NULL;
    return phead;
}

void InsertNode(Node* phead, int data)
{
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = NULL;
    
    Node* cur = phead;
    while (cur->next != NULL)
    {
    cur = cur->next;
    }
    cur->next = newNode;
}

void ShowList(Node* phead)
{
    Node* cur = phead;
    while (cur != NULL)
    {
    printf("%d ", cur->data);
    cur = cur->next;
    }
    printf("\n");
}

Node* ReverseList(Node* phead)
{
    if (phead == NULL || phead->next == NULL)
    {
    return phead;
    }
    
    Node* prev = NULL;
    Node* cur = phead;
    Node* next = NULL;
    
    while (cur != NULL)
    {
	    next = cur->next;
	    cur->next = prev;
	    prev = cur;
	    cur = next;
    }
    
    return prev;
}

int main(void)
{
    int n;
    scanf("%d", &n);
    
    int data;
    scanf("%d", &data);
    Node* phead = CreateList(data);
    
    int i;
    for (i = 1; i < n; i++)
    {
    scanf("%d", &data);
    InsertNode(phead, data);
    }
    	printf("链表逆置前的数据:\n"); 
    ShowList(phead);
    
    Node* reversedList = ReverseList(phead);
    printf("链表逆置后的数据:\n");
    ShowList(reversedList);
    
    return 0;
}
posted on 2023-12-23 19:34  lulixiu  阅读(87)  评论(1)    收藏  举报