Coursera_北大_C_language_结构体 & 链表

结构体:

用一组变量来描述同一个“事物”

定义与赋值:

struct student	//名字为student的结构体类型。
{
	int id;
	char name[20];
	char sex;
	int age;
	float score;
	chaar addr[30];
};

student不是一个变量,而是一种数据类型。用来定义变量的东西。是组合数据类型。
利用结构体定义变量:法1:

student student1,student2;

和传统变量定义一样。
法2:

struct student	//名字为student的结构体类型。
{
	int id;
	char name[20];
	char sex;
	int age;
	float score;
	chaar addr[30];
}student_1,student_2;//注意分号位置。
#include <iostream>
using namespace std;
struct student
{
	int id_num;
	char name[10];
};
int main(){
	student mike = {123,{'m','i','k','e','\0'}};
	mike.id_num = 20191111 + mike.id_num;
	for (int i = 0; mike.name[i] != '\0'; i++)
		mike.name[i] = toupper(mike.name[i]);
	cout << mike.id_num << " " << mike.name << endl;
	return 0;
}

利用mike.id_num来索引学号。(和python中的类类似)。

结构体可以直接赋值。

student mike1 = {123,{'m','i','k','e','\0'}};
student mike2;
mike2 = mike1; 
/*相当于是直接copy了一份mike1给mike2.
然后可以对mike2进行修改。如:*/
mike2.id_num = 20130000;

结构体变量也可以做函数参数。

void renew(student one)
{
	one.id_num = 00000000;
	cout << one.id_num << endl;
}
int main()
{
	student mike1 = {123,{'m','i','k','e','\0'}};
	renew(mike)
	cout << mike.id_num << endl;
	return 0;
}
结果为
00000000
123

在定义函数中相当于把结构体copy了一份进入renew里,renew里对one的任何修改都不会改变结构体mike 的值。

和数组不同,数组做定义函数参数时是传递地址,但是结构体是纯copy。

指向结构体变量的指针:

struct student
{
	int id_num;
	char name[10];
};
int main()
{
	student mike = {123,{'m','i','k','e','\0'}};
	student *one = &mike;
	cout << (*one).id_num << " " << (*one).name;
	return 0;
}
结果为
123 mike

如果换一种输出形式:
	cout << one->id_num << " " << one->name;
结果是一样的。

->是指向运算符。对指针指向的结构体变量的成员变量进行访问。

如果用指向结构体的指针作为函数的参数。那么就会不同于之前将结构体本身作为函数参数。它会直接访问主函数结构体的内容并进行修改。

结构体的数组特性

student myclass[3] = {123,{'m','i','k','e','\0'},133,{'t','o','m','\0'},143,{'j','a','c','k','\0'}};
student *one = myclass;
cout << one->id_num << endl;
one++;
cout << one->id_num << endl;
结果为:
123
133

经过一次one++后,实际上是跨过一整个结构体。

结构体数据类型的特性与普通数据类型的特性是一致的。

但是利用结构体的数组特性不方便在两个元素之间插入新的元素,但是链表就很方便。

链表:

用指针把结构体链起来。在这里插入图片描述

  • 链表头:指向第一个链表节点的指针;
  • 链表节点:链表中的每一个元素,包括:
    - 当前节点的数据
    - 下一个节点的地址
  • 链表尾:不再指向其他结点的结点,其地址部分放一个NULL,表示链表就此结束。

链表的创建:
链表可以动态地创建。
动态地申请内存空间。

运算符: new,delete
new:开辟一个动态的存储空间,并返回其起始地址。
delete:释放一个指针指向的存储空间。

int *pint = new int(1024);		delete pint;
int *pia = new int[4]; 			delete[] pia;

new 后面跟上想要存放的数据类型。而且也可以在()上加上数据空间上的初始值。能返回一个指向这个内存空间的地址。

struct student
{
	int id;
	student *next;
};
student *head;
head = new student;

创建的顺序如下:

  1. head = new student;
    student *temp = head;
  2. Continue?
    Y:temp -> next = new student;
    temp = temp -> next;
    goto 2
    N:temp->next = NULL

代码为:

student *create()
{
	student *head, *temp; int num, n = 0;
	head = new student;
	temp = head;
	cin >> num;
	while (num != -1)
	{
		n++;
		temp -> id = num;
		temp -> next = new student;
		temp = temp -> next;
		cin >> num;
	}
	if (n == 0) head = NULL; else temp -> next = NULL;
	return head;
}

链表的操作:

  1. 遍历:
struct student
{
	int id;
	student *next;
};
student *create();
int main()
{
	student *pointer = create(); //就是上面那个代码块的定义函数create()返回一个指向链表头部的指针head。
	while (pinter -> next != NULL)
	{
		cout << pointer->id << endl;
		pointer = pointer->next;
	}
	return 0;
}
  1. 删除结点:
    首先利用temp指针找到要删除的结点。如果是第一个结点,则可以 temp = head;head = head->next;delete temp;
    如果是删除中间结点,则需要两个辅助的指针。在temp寻找需要删除的结点同时,需要另一个指针follow跟在temp后面。然后再follow -> next = temp ->next ; delete temp;
    完整代码:
linker *dele(student *head; int n)
{
	student *temp, *follow;
	temp = head;
	if (head == NULL){	//head为空的方法。
		return (head);
	}
	if (head -> num == n){	//n为第一个的方法。
		head = head -> next;
		delete temp;
		return (head);
	}
	while (temp != NULL && temp -> num != n){
		follow = temp;
		temp = temp->next;
	}
	if (temp == NULL) cout << "not found";
	else{
		follow -> next = temp -> next;
		delete temp;
	}
	return (head);
}
  1. 插入结点。
    类似链表的删除,代码如下:
Student *insert(student *head; int n){
	student *temp, *unit, *follow;
	temp = head; unit = new student;
	unit -> num = n; unit -> next = NULL;
	if (head == NULL){
		head = unit;
		return (head);
	}
	while ((temp -> next != NULL) && (temp -> num < n)){
		follow = temp;
		temp = temp -> next;
	}
	if (temp == head){
		unit ->next = head; head = unit;
	}
	else{
		if (temp -> next == NULL) temp -> next = unit;
		else{
			follow->next = unit;unit->next = temp;
		}
	}
	return (head);
}
  1. 双向链表。
    即每个结点都有两个指针,一个指向后个,另一个指向前个。在这里插入图片描述

删除:

temp -> ahead -> next = temp -> next;
temp -> next -> ahead = temp -> ahead;

添加:

unit -> next = temp -> next;
unit -> ahead = temp;
temp -> next -> ahead = unit;
temp -> next = unit;

可以利用链表解决约瑟夫问题。
就是那种圆圈的绕环的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值