什么是链表? 链表是一种常见的重要的数据结构,是动态地进行存储分配的一种结构。 链表的组成: 头指针:存放一个地址,该地址指向第一个元素。 结点:用户需要的实际数据和链接节点的指针
.
#include <stdio.h>
#include <stdlib.h>
struct stu
{
int num;
float score;
struct stu *next;
};
int main()
{
struct stu a,b,c,*head;
a.num = 10101;
a.score = 95;
b.score = 89.5;
b.num = 10105;
c.num = 10107;
c.score = 85;
head = &a;
a.next = &b;
b.next = &c;
while(head != NULL)
{
printf("%d %f\n",head->num,head->score);
head = head->next;
}
return 0;
}
建立动态链表
所谓建立动态 链表是指在程序执行过程中从无到有地建立起一个链表,即一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系。 例题: 一个程序建立一个含有学生(学号,成绩)数据的单向动态链表。 约定: 学号不会为0,如果输入的学号为0,表示链表建立过程完成,该结点不会连接到链表中
如果输入的p1->num 不等于0,则输入的是第一个结点数据(n = 1), 令 head = p1,即把p1的值赋给 head,也就是使head 也指向新开辟的结点,p1所指向的新开辟的结点就成为了链表中第一个结点。
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define LEN sizeof(struct student)
struct student *creat();
void print (struct student *head);
struct student
{
int num;
float score;
struct student *next;
};
int n;
int main()
{
struct student *stu;
stu = creat();
print(stu);
return 0;
}
struct student *creat()
{
struct student *p1,*p2;
struct student *head;
p1=p2=(struct student*)malloc(LEN);
printf("please intput num:");
scanf("%d",&p1->num);
printf("please input score:");
scanf("%f",&p1->score);
head = NULL;
n=0;
while (p1->num != 0)
{
n++;
if(n == 1)
{
head = p1;
}
else
{
p2->next = p1;
}
p2=p1;
p1=(struct student*)malloc(LEN);
printf("please intput num:");
scanf("%d",&p1->num);
printf("please input score:");
scanf("%f",&p1->score);
}
p2->next = NULL;
return head;
}
void print(struct student *head)
{
struct student *p;
p = head;
printf("there are %d record!\n",n);
while (head != NULL)
{
printf("%d %f\n",p->num,p->score);
p=p->next;
}
}
对链表的删除
从一个动态链表中删去一个结点,并不是真正从内存中把它抹掉,而是把它从链表中分离开来,只要撤销原来的链接关系即可。
题目: 写一个函数用来删除动态链表中指定的结点。 解题思路: 1.从p指向的第一个结点开始,检查该结点中的Num值是否等于输入的要求,删除的那个学号。 2.如果相等就将该结点删除,如不相等,就将p后移一个结点,再如此下去,再如此进行下去,直到遇到表尾为止。
3.可以设置两个指针变量p1,p2,先使p1指向第一个结点。 4.如果要删除的不是第一个结点,则使p1后移指向下一个结点(将p1-next = p1),在此之前应将p1的值赋给p2(p2=p1),使p2 指向刚才检查过的那个结点。
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define LEN sizeof(struct student)
struct student {
int num;
float score;
struct student *next;
};
struct student *creat();
void print(struct student *head);
struct student *del(struct student *head, int num);
int n;
int main() {
struct student *stu;
stu = creat();
print(stu);
printf("del a num:\n");
int a;
struct student *p;
scanf("%d", &a); // 修正此处的 scanf
p = del(stu, a);
print(p);
return 0;
}
struct student *creat() {
struct student *p1, *p2;
struct student *head = NULL;
p1 = p2 = (struct student*)malloc(LEN);
printf("please input num:");
scanf("%d", &p1->num);
printf("please input score:");
scanf("%f", &p1->score);
n = 0;
while (p1->num != 0) {
n++;
if (n == 1) {
head = p1;
} else {
p2->next = p1;
}
p2 = p1;
p1 = (struct student*)malloc(LEN);
printf("please input num:");
scanf("%d", &p1->num);
printf("please input score:");
scanf("%f", &p1->score);
}
p2->next = NULL;
free(p1); // 释放最后一个多余的节点
return head;
}
void print(struct student *head) {
struct student *p = head;
printf("there are %d record(s)!\n", n);
while (p != NULL) {
printf("%d %f\n", p->num, p->score);
p = p->next;
}
}
struct student *del(struct student *head, int num) {
struct student *p1 = head, *p2 = NULL;
if (head == NULL) {
printf("error: list is empty\n");
return head;
}
while (p1->num != num && p1->next != NULL) {
p2 = p1;
p1 = p1->next;
}
if (p1->num == num) {
if (p1 == head) {
head = p1->next;
} else {
p2->next = p1->next;
}
free(p1); // 释放被删除的节点
n--; // 更新记录数
} else {
printf("error: num not found\n");
}
return head;
}
对链表的插入
对链表的插入是指将一个结点插入到一个已有的链表中。 为了能够做到正确插入,必须解决两个问题。 ①怎么找到插入的位置 ②怎样实现插入 我们可以先用指针变量p0 指向待插入的结点,p1指向第一个结点。将p0->num与p1->num相比较,如果p0->num > p1->num,此时将p1往后移,并使p2指向刚才p1所指的结点。
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define LEN sizeof(struct student)
struct student {
int num;
float score;
struct student *next;
};
struct student *creat();
void print(struct student *head);
struct student *del(struct student *head, int num);
struct student *add(struct student *head,struct student *stu1);
int n;
int main() {
struct student *stu;
stu = creat();
print(stu);
printf("del a num:\n");
int a;
struct student *p;
scanf("%d", &a); // 修正此处的 scanf
p = del(stu, a);
print(p);
struct student *mn;
printf("please add stu input num :");
scanf("%d",&mn->num);
printf("please add stu input score :");
scanf("%f",&mn->score);
struct student *p2;
p2 = add(stu,mn);
print(p2);
return 0;
}
struct student *creat() {
struct student *p1, *p2;
struct student *head = NULL;
p1 = p2 = (struct student*)malloc(LEN);
printf("please input num:");
scanf("%d", &p1->num);
printf("please input score:");
scanf("%f", &p1->score);
n = 0;
while (p1->num != 0) {
n++;
if (n == 1) {
head = p1;
} else {
p2->next = p1;
}
p2 = p1;
p1 = (struct student*)malloc(LEN);
printf("please input num:");
scanf("%d", &p1->num);
printf("please input score:");
scanf("%f", &p1->score);
}
p2->next = NULL;
free(p1); // 释放最后一个多余的节点
return head;
}
void print(struct student *head) {
struct student *p = head;
printf("there are %d record(s)!\n", n);
while (p != NULL) {
printf("%d %f\n", p->num, p->score);
p = p->next;
}
}
struct student *del(struct student *head, int num) {
struct student *p1 = head, *p2 = NULL;
if (head == NULL) {
printf("error: list is empty\n");
return head;
}
while (p1->num != num && p1->next != NULL) {
p2 = p1;
p1 = p1->next;
}
if (p1->num == num) {
if (p1 == head) {
head = p1->next;
} else {
p2->next = p1->next;
}
free(p1); // 释放被删除的节点
n--; // 更新记录数
} else {
printf("error: num not found\n");
}
return head;
}
struct student *add(struct student *head,struct student *stu1)
{
struct student *p0,*p1,*p2;
p0 = stu1;
p1 = head;
if (head == NULL)
{
head = p0;
p0->next = NULL;
}
else
{
while ((p0->num > p1->num) && (p1->next !=NULL))
{
p2 = p1;
p1 = p1->next;
}
if ((p0->num < p1->num) && (p1->next != NULL))
{
if (head == p1)
{
head = p0;
p0->next = p1;
}
else
{
p2->next = p0;
p0->next = p1;
}
}
else
{
p1->next = p0;
p0->next = NULL;
}
}
n = n+1;
return head;
};
用typedef 定义类型
用typedef 声明新的类型名来代替已有的类型名 声明 INTEGER 为整型 Typedef int INTEGER
声明 NUM 为整型数组类型 typedef int NUM[100];
用typedef 声明新的类型名来代替已有的类型名 声明 INTEGER 为整型 Typedef int INTEGER 表明结构类型 Typedef struct { int month; int day; int year; }DATE;
#include <stdio.h>
typedef struct
{
int month;
int day;
int year;
}DATE;
void main()
{
DATE date_one;
date_one.month = 12;
date_one day = 31;
date_one.year = 1995;
printf(“%d - %d - %d \n ”,date_one.year,date_one.month,date_one.day);
}
声明 SRTING 为字符指针类型
typedef char* p;
Void main()
{
p p1;
p1 = “mou mou is very hand”;
printf(“%s\n”,p1);
}
声明 POINT 为指向函数的指针类型,该函数返回整型值 typedef int (*POINT)();
typedef void (*p)();
Void fun();
Void main()
{
p p1;
p1 = fun;
(p1)();
}
Void fun()
{
printf(“mou mou is very handsome!\n”);
}
先按定义变量的方法写出定义体,如 inti 将变量名换成新类型名(例如将i换成COUNT) 在最前面加typedef例如: typedef int COUNT 然后可以用新类型名去定义变量 COUNT i,j;
用typedef可以声明各种类型名,但不能用来定义变量。 用typedef只是对已经存在的类型增加一个类型名,而没有创造新的类型。 当不同源文件中用到同一类型数据时,常用typedef声明一些数据类型,把它们单独放在一个文件中,然后在需要用到它们的文件中用 #include 命令把他们包含进来。使用typedef 有利于程序的通用与移植 Typedef与#define有相似之处,例如:typedef int COUNT;#define COUNT int 的作用都是用COUNT 代替int.但是,它们二者是不同的。 #define 是在预编译时处理的,它只能作简单的字符串替换,而typedef是在编译时处理的。实际上它并不是作简单的字符串替换,而是采用如同定义变量的方法那样来声明一个类型。
Typedef (int *) p1; 和 #define p2 int*
位运算
位运算是指按二进制位运算进行的运算,因为在系统软件中,常要处理二进制位的问题。 例如:将一个存储单元中的各二进制位左移或右移一位,两个数按位相加等。 C语言提供位运算的功能,与其他高级语言相比,具有很大的优越性。
1.位运算符中除 ~ 以外,均为双目运算符,即要求两侧各有一个运算量。 2.运算量只能是整型或字符型的数据,不能为实型数据。
按位与 运算的用途
清零 若相对一个存储单元清零,即使其全部二进制位为0,只要找一个二进制数,其中各个位符合以下条件: 原来的数中位1的位,新数中相应位为0,然后使二者进行 & 运算,即可达到清零目的。 例如: 要求将二进制数 1110 0101 的第二位清零
2.取一个数中某些指定位 例如: 我们需要对一个字符数据取出其低八位的值时,我们可以这么做。
左移运算符是用来将一个数的各二进制位全部左移若干位。 例如: a = << 2 将a的二进制数左移2 位,右边补0. 若 a = 15, 即二进制数 0000 1111,左移2位得, 0011 1100(十进制数60)。 若高位左移后溢出,舍弃。
左移1 位相当于该数乘以2,左移两位相当于该数乘以4, 15<<2 = 60,即乘了4。 但此结论只适用于该数左移时被溢出舍弃的高位中不包含1的情况。 假设一个字节(8)位存一个整数,若a为无符号整型变量,则a = 64时,左移一位时溢出的是0,而左移2位时,溢出的高位中包含1。 100 0000 1000 0000
右移运算符是a >>2表示将a的各二进制位右移2位,移到右端的低位被舍弃,对无符号数,高位补0。 例如: a = 017时, a的值用二进制形式表示为 00001111,舍弃低2位11,得到: a >>2 === 0000 0011 右移一位相当于除以2 右移n位相当于除于2^n
对无符号数,右移时左边高位移入0; 对于有符号的值,如果原来符号位位0,(该数为正),则左边也是移入0 如果符号位原来位1(即负号),则左边移入0还是1,要取决于所用的计算机系统。有的系统移入0,有的系统移入1。 移入0的称为 “逻辑右移”,即简单右移;移入1的称为“算术右移”。
void main()
{
unsigned char a = -2;
a >> 1 ;
printf(“%d \n\n”,a); // 0111 1111
}