数据结构笔记二

		
预习:
	结构和指针:
	
		计算机存储和处理数据基本上都放在内存中,如何管理呢?? 
			用变量对应一块内存。
	
		变量-----代表  一块内存
		
		
		
		int i = 1;
		int j = 5;

		i,j分别对应一块内存
		
		变量类型----决定内存的大小。
		
		int i = 1;//4个字节
		char c = 'c'; //1个字节
		
		变量类型--简单类型和复合类型
		简单类型:int  char float double 
		复合类型:结构、联合和枚举
		
		
		布尔类型--C89没有布尔类型,但在c99加入了_Bool类型(强加的类型)
		
	结构是什么?
		
		多个数据放在一起,构成了结构。结构其实就是一片连续的内存,可以存放任意数量的任意类型的数据。
		
		一般来说,多个不同类型的相关数据放在一起的办法就是结构。
	
		struct Emp{//员工的数据封在结构中
			int num;//员工编号
			char  name[20];//员工的姓名
		};
		
		struct Emp 作为一个类型出现,这个类型包括所有的成员。在C语言中,此类型为struct Emp,sturct不能省。
		
		struct Emp emp 其实就是结构对应的一块内存,在这块内存中,成员从上到下依次排列。(有对齐和补齐的字节数:注意)
		
		
		结构的地址需要&取一下。	
		指针、数组、字符串不需要&。
		
		
		取结构的成员有两种常见的方式:
		
		(1)(结构的使用)
		struct Emp emp;
		emp.num = 1;
		
		(2)(结构指针的使用)
		struct Emp* pe = malloc(sizeof(struct Emp));
		pe->num = 1;
		
  1 #include <stdio.h>
  2 
  3 struct Emp{
  4     int id;//4
  5     char name[18];//18?20>
  6     int age;//4
  7 };
  8 
  9 int main()
 10 {
 11     struct Emp emp;
 12     printf("size=%d\n",sizeof(emp));//28,age有对齐
 13     printf("emp=%p\n",emp);//-1代表错误地址 warning.
 14     printf("emp=%p\n",&emp);//正确
 15     printf("emp.id=%p\n",&emp.id);//结构的地址与第一个元素的地址相同的
 16     printf("emp.name=%p\n",emp.name);//字符串不需要加&取地址
 17     printf("emp.age=%p\n",&emp.age);
 18     return 0;
 19 }
		
		
指针:
		int  fa(){
			int y = 200;
			return y;
		}
		int main()
		{
			int x = 100;//希望x能够把fa()结果返回
			x = fa();
		}
	

	一般来说,变量名 代表的是 一块内存,但在使用时,变量名 是无法直接获取的。
	
	变量等于内存中的数据。而想获取变量对应的内存地址需要用&,这种变量地址的类型就是指针。
	
	
	
	int x = 1;
	x就相当于1
	int * pi = &x;
	pi就是x的地址,而不是1.
	pi也是一个变量,也对应一块内存。
	
	
	pi 代表的是x的地址,如果想取x的数据,用*pi,就是1.
	pi和&x都是x的地址;  
	*pi和x都是x的数据;
	
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 void fa(int x,int *pi){
  4     printf("x=%d\n",x);//x = 100
  5     printf("pi=%p,*pi=%d\n",pi,*pi);//pi = 地址, *pi 100
  6     x = 200;
  7     *pi = 200;
  8 
  9 }
 10 int main()
 11 {
 12     int a = 100;
 13     int b = 100;
 14     int * pb = &b;
 15     printf("pb =%p\n",pb);
 16     fa(a,pb);
 17     printf("a=%d,b=%d\n",a,b);//a =100; b =200
 18     return 0;
 19 }


 
数据结构之队列Queue:----应用非常广泛(OS里面的消息队列;网络编程 )

	队列的特点:
	
		先进(压入push)先出(弹出pop),后进后出。
		
	
	void fa(){
		int a;
		if (a>5){
			int b;
		}//b出栈
	}//a出栈
	----先进后出 
	
	int main(){
		int c;
		fa();
		fb();
	}
	变量定义的顺序:c,a,b   出栈顺序b,a,c 
	
	----每一个函数都有一个函数栈
	
	所有函数都是使用栈存储数据的(函数栈),只要数据需要排队的都是需要队列。

	
	队列包括一个队首和一个队尾,放入元素在队尾的后面并以新元素为新的队尾,
取出的元素就是队首并把下一个元素作为新的队首。


基于顺序表(数组)的队列 下标要循环利用,到最大值以后就要回到0,放入时找队尾下标,取出找队首下标


	(圆)数组有5个元素,下标为0-4;
	一开始没有数据时,队首和队尾下标都是0开始;
	没有人出队时,队首的下标就是0;
	放入第1个元素10时,队首下标不变0,队尾下标后移至1;
	放入第2个元素20时,队首元素10下标不变0,第2个元素为20下标为1,队尾下标后移至2;
	放入第3个元素30时,30下标为2队尾下标为3
	放入第4个元素40时,40下标为3队尾下标为4
	放入第5个元素50时,50下标为4队尾下标为0了----数组满了。队列满了。
	
	当队首和队尾重合在一起时,如果不是空的就是满的。
	
	
	移除元素第一个元素时,10出队,队首下标指向1了,队尾下标不变。
	进入一个元素60时,60进队,队首下标指向1了,队尾下标也指向1了。---数组和队列又满了
	
	数组实现队列的时候一定要考虑  下标回零 的问题。
	
	
	struct Queue{
		int * arr;//数组的首地址
		size_t cap;//数组的长度  容量
		size_t front;//队首前端、对手下标
		size_t rear;//队列后端、队尾下标
		size_t size;//队列中元素的个数,为了区分front和rear所处位置相同时
	};
	
	运算结构: 
		创建和销毁
		入队和出队
		判空和判满
		查看元素个数
		查看队首不能查看队尾
qa.h 		
  1 #ifndef _QA_H
  2 #define _QA_H
  3 #include <sys/types.h>
  4 typedef struct Queue{
  5     int * arr;//数组的首地址
  6     size_t cap;//数组的容量,数组的长度
  7     size_t front;//队首下标
  8     size_t rear;//队尾下标
  9     size_t size;//真实存在的元素的数量
 10 }QUEUE;
 11 //初始化队列函数
 12 void queue_init(QUEUE* queue,size_t cap);
 13 //回收队列函数
 14 void queue_deinit(QUEUE* queue);
 15 //判断队满
 16 int queue_full(QUEUE* queue);
 17 //判断队空
 18 int queue_empty(QUEUE* queue);
 19 //入队函数
 20 void queue_push(QUEUE* queue,int data);
 21 //出队函数
 22 int queue_pop(QUEUE* queue);
 23 //查看队首函数
 24 int queue_front(QUEUE* queue);
 25 //查看队列大小函数
 26 size_t queue_size(QUEUE* queue);
 27 #endif
		
qa.c
  1 #include <stdlib.h>
  2 #include "qa.h"
  3 //初始化队列函数
  4 void queue_init(QUEUE* queue,size_t cap){
  5     queue->arr = malloc(sizeof(int)*cap);
  6     queue->cap = cap;
  7     queue->front = 0;
  8     queue->rear = 0;
  9     queue->size = 0;
 10 }
 11 //回收队列函数
 12 void queue_deinit(QUEUE* queue){
 13     free(queue->arr);
 14     queue->arr = NULL;
 15     queue->cap = 0;
 16     queue->front = 0;
 17     queue->rear = 0;
 18     queue->size = 0;
 19 }
 20 //判断队满
 21 int queue_full(QUEUE* queue){
 22     return queue->size >= queue->cap;
 23 }
 24 //判断队空
 25 int queue_empty(QUEUE* queue){
 26     return !queue->size;
 27 }
 28 //入队函数
 29 void queue_push(QUEUE* queue,int data)
 30 {//判断队尾下标是否到达最大值,如果是最大值了就回0;还要判断是否满;---在这里没判断满,在应用时要判断满。
 31     if (queue->rear >= queue->cap) queue->rear = 0;//下标增加
 32     queue->arr[queue->rear] = data;//数据放队尾
 33     queue->rear++;//队尾后移
 34     queue->size++;//元素数量加
 35 }
 36 //出队函数
 37 int queue_pop(QUEUE* queue){
 38     if (queue->front >= queue->cap) queue->front = 0;
 39     queue->size--;//元素的数量减少
 40     //int temp = queue-> arr[queue->front];
 41     //queue->size--;//元素的数量减少
 42     //return temp;
 43     return queue->arr[queue->front++];
 44 }
 45 //查看队首函数
 46 int queue_front(QUEUE* queue){
 47     if (queue->front >= queue->cap) queue->front = 0;
 48     return queue->arr[queue->front];
 49 }
 50 //查看队列大小函数
 51 size_t queue_size(QUEUE* queue){
 52     return queue->size;
 53 }
 54 
   
-------------------------------------------------------------------------
测试用例1:
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include "qa.h"
  4 int main()
  5 {
  6         QUEUE  queue;
  7         queue_init(&queue,5);
  8         int i;
  9         if (!queue_full(&queue)){
 10                 for (i=0;i<5;i++)
 11                 {
 12                         queue_push(&queue,i);
 13                 }
 14         }
 15         printf("size=%d\n",queue_size(&queue));
 16         if (!queue_empty(&queue)){
 17                 for (i=0;i<5;i++)
 18                 {
 19                         printf("%d\n",queue_pop(&queue));
 20                 }
 21         }
 22         printf("size=%d\n",queue_size(&queue));
 23         queue_deinit(&queue);
 24 
 25         return 0;
 26 }
~                     

--------------------------------------------------------------------
测试用例2:
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include "qa.h"
  4 int main(){
  5         QUEUE  queue;
  6         queue_init(&queue,5);
  7         int i;
  8         for (i=0;i<20;i++){
  9                 if (queue_full(&queue))
 10                 {
 11                         printf("size=%d\n",queue_size(&queue));
 12                         printf("pop %d\n",queue_pop(&queue));
 13                         printf("size=%d\n",queue_size(&queue));
 14                 }
 15                 else
 16                 {
 17                         printf("size=%d\n",queue_size(&queue));
 18                         queue_push(&queue,i);
 19                         printf("insert %d\n",i);
 20                         printf("size=%d\n",queue_size(&queue));
 21                 }
 22         }
 23         printf("size=%d\n",queue_size(&queue));
 24         if (!queue_empty(&queue)){
 25                 for (i=0;i<5;i++){
 26                         printf("%d\n",queue_pop(&queue));
 27                 }
 28         }
 29         printf("size=%d\n",queue_size(&queue));
 30         queue_deinit(&queue);
 31         return 0;
 32 }

 ----------------------------------------------------------------------
 测试用例3:
  1 #include <stdlib.h>
  2 #include <stdio.h>
  3 #include "qa.h"
  4 
  5 int main()
  6 {
  7 
  8     QUEUE queue;//创建队列
  9 
 10     queue_init(&queue,5);
 11 
 12     int i;
 13     for(i=0;i<5;i++){
 14         if (!queue_full(&queue))//如果队列不满就加
 15         {
 16             queue_push(&queue,i);
 17         }   
 18     }
 19 
 20     printf("size = %d\n",queue_size(&queue));
 21     //queue.front = 0;
 22     while(!queue_empty(&queue)){
 23 
 24         printf("%d\n",queue_pop(&queue));
 25     
 26     }
 27     queue_deinit(&queue);
 28 }
 

-------------------------------------------------------------------------   

	
基于链表式的队列  没有满,只有判断空。

	动态分配、前后指针、注意判空
	
	链表式的队列 需要两个结构:节点 和 队列
	
		struct QueueNode{
			int data; //数据
			struct QueueNode * next;//下一个节点的地址
		};
		
		struct Queue{
			struct QueueNode* front;//队首节点
			struct QueueNode* rear;//队尾节点
		};
	
		放入队列 找 队尾节点,弹出队列找队首节点。

		
空队列没有节点: 队首指针和队尾指针都是空的,节点是空的;
		
一开始队列front和rear都是NULL。
放入第一个元素时,front和rear都指向第一个元素,再放入时,front不变,改变的是rear的指向和原来的rear的next。
(放入第二个元素时,front的指针不变,队尾的指针要变;)(队尾的next总是为null。)

出队时,改变front,指向next并释放节点内存,但删除最后一个时,rear也要改成NULL。

----------------------------------------------------------------------------
ql.h

  1 #ifndef _QL_H
  2 #define _QL_H
  3 #include <sys/types.h>
  4 typedef struct QueueNode{//链式表的节点
  5     int data;//数据
  6     struct QueueNode * next;//下一个元素的地址
  7 }QUEUE_NODE;
  8 typedef struct Queue{//队列
  9     QUEUE_NODE *front;//队首节点地址 负责出队
 10     QUEUE_NODE *rear;//队尾节点地址 负责入队
 11 }QUEUE;
 12 void queue_init(QUEUE* queue);//初始化为空
 13 void queue_deinit(QUEUE* queue);//释放节点后删除
 14 int queue_empty(QUEUE* queue);//判断是否为空
 15 void queue_push(QUEUE* queue,int data);//入队
 16 int queue_pop(QUEUE* queue);//出队
 17 int queue_front(QUEUE* queue);//队首查看
 18 size_t queue_size(QUEUE* queue);//取元素数量
 19 #endif

 --------------------------------------------------------------------------
 ql.c 
 
  1 #include <stdlib.h>
  2 #include "ql.h"
  3 static QUEUE_NODE* create_node(int data){
  4     QUEUE_NODE* node = malloc(sizeof(QUEUE_NODE));
  5     node->data = data;
  6     node->next = NULL;//队列的新节点next必须为NULL,都是加在队尾的
  7     return node;
  8 }
  9 static QUEUE_NODE* destroy_node(QUEUE_NODE * node){
 10     QUEUE_NODE * next = node->next;//node->next当前队首节点指向的下一个节点,将会变成新的队首。
 11     free(node);//释放当前节点
 12     return next; //返回新的队首的地址
 13 }
 14 void queue_init(QUEUE * queue){//初始化为空
 15     queue->front = NULL;
 16     queue->rear = NULL;
 17 }
 18 void queue_deinit(QUEUE * queue){//释放节点后删除
 19     while(queue->front)
 20         queue->front = destroy_node(queue->front);
 21     queue->rear = NULL;
 22 
 23 }
 24 int queue_empty(QUEUE* queue){//判断是否为空
 25     return (!queue->front) && (!queue->rear);
 26 
 27 }
 28 void queue_push(QUEUE* queue,int data){//入队(需要深刻理解)
 29     QUEUE_NODE* node = create_node(data)
 30     if (queue->rear)//不是第一个
 31         queue->rear->next = node;//改的是原先的队尾的next
 32     else//是第一个
 33         queue->front = node;
 34     queue->rear = node;
 35 }
 36 int queue_pop(QUEUE* queue){//出队
 37     int data = queue->front->data;
 38     queue->front = destroy_node(queue->front);
 39     if (!queue->front) queue->rear = NULL;
 40     return data;
 41 }
 42 int queue_front(QUEUE* queue){//队首查看
 43     return queue->front->data;
 44 
 45 }
 46 size_t queue_size(QUEUE* queue){//取元素数量
 47     size_t size = 0;
 48     QUEUE_NODE* node;
 49     for (node = queue->front;node;node=node->next)
 50     {
 51         size++;
 52     }
 53     return size;
 54 }

 
 --------------------------------------------------------------
  1 #include <stdlib.h>
  2 #include <stdio.h>
  3 #include "ql.h"
  4 
  5 int main()
  6 {
  7 
  8     QUEUE queue;//创建队列
  9 
 10     queue_init(&queue);
 11 
 12     int i;
 13 
 14     for(i=0;i<5;i++){
 15 
 16             queue_push(&queue,i);
 17     }
 18 
 19     printf("size = %d\n",queue_size(&queue));
 20 
 21     //queue.front = 0;
 22     while(!queue_empty(&queue)){
 23 
 24         printf("%d\n",queue_pop(&queue));
 25 
 26     }
 27 
 28     queue_deinit(&queue);
 29 }

 --------------------------------------------------------------
 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值