结构体:
用一组变量来描述同一个“事物”
定义与赋值:
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;
创建的顺序如下:
- head = new student;
student *temp = head; - 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;
}
链表的操作:
- 遍历:
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;
}
- 删除结点:
首先利用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);
}
- 插入结点。
类似链表的删除,代码如下:
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);
}
- 双向链表。
即每个结点都有两个指针,一个指向后个,另一个指向前个。
删除:
temp -> ahead -> next = temp -> next;
temp -> next -> ahead = temp -> ahead;
添加:
unit -> next = temp -> next;
unit -> ahead = temp;
temp -> next -> ahead = unit;
temp -> next = unit;
可以利用链表解决约瑟夫问题。
就是那种圆圈的绕环的。