链表---typedef----位运算

什么是链表? 链表是一种常见的重要的数据结构,是动态地进行存储分配的一种结构。 链表的组成: 头指针:存放一个地址,该地址指向第一个元素。 结点:用户需要的实际数据和链接节点的指针

.

#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
}

  • 14
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值