把以前写的东西贴在这里方便回故
以前我们建立一个队列.一开始接口不太友好.后来我们进行了优化.
Queue abc; //声明队列结构体 crteate_Queue(abc); //创建队列 abc.push(int num); //压入 int abc = abc.pop();//弹出
大致是这样子的.但是我们发现,这个队列有一个非常明显的缺陷.那就是,只能push进int型的变量,如果我们想要压进去其它类型.甚至是自定义类型.那么,我们就得对这个队列程序进行大刀阔斧似的改变.几乎所有的代码都改了,但是代码的逻辑却是一模一样,让人"捉急",不甘心,逻辑一模一样的代码,每次改变类型,我们需要去修改大部分代码才能使用,这样的程序是我们不想要的.所以我们需要一个通用的队列,它的目标是:
1.我们不需要去修改队列的代码.
2.它能push进任何类型
如果在C++,有模板类,可以很容易解决这个问题,但是在C里,我们只好想一个巧妙的办法来完成这个任务.
首先,我们只考虑队列,它的数据结构是这样的:
typedef struct _Node{ struct _Queue * prev; struct _Queue * next; }Node; typedef Node* Node_Pion; //它的指针类型
然后是它的行为:
Node_Pion node_push(Node_Pion tail, Node_Pion node) //给我一个尾指针,一个结点. { if (!node) return NULL; if(tail) tail-next = node; node->prev = tail; tail = node; return tail; } Node_Pion node_pop (Node_Pion head) //给我一个头指针. { if(head-next) head->next->prev = NULL; head = head->next; return head; }
从上面看出,这里和昨天并无什么 太大的区别.
下面是关键..
然后我们对这个队列进行封装:
typedef struct _Queue{ Node_Pion HEAD; //它的头 Node_Pion TAIL; //它的尾 }Queue; typedef Queue* Queue_pion; //它的行为 //构造 Queue_pion ctreate_queue(Queue_pion queue){ if(!queue) queue = (Queue_pion)malloc(sizeof(_Queue)); queue->HEAD = NULL; queue->TAIL = NULL; return queue; } //析构 void delete_queue(Queue_pion queue){ free(queue); } //压入 void push (Queue_pion queue, void* node){ if((!queue->HEAD) && (!queue->TAIL)) //如果头尾有一个等于NULL.队列无效 queue->TAIL = queue->HEAD = node_push(queue->TAIL, (Node_Pion)node); //重新建立队列 else queue->TAIL = node_push(queue->TAIL, (Node_Pion)node); //给我一个尾指针,一个结点. } //弹出 void* pop (Queue_pion queue){ Node_Pion p = queue->HEAD; queue->HEAD = node_pop(queue->HEAD); return (void*)p; }
这样,我们在使用时就比较好玩了
比如,我们有一个自定义的类型
struct abc{ int num; int val; };
然后,我们在代码里,构造一个队列:
Queue *abc = ctreate_queue(Queue_pion queue); typedef struct _abc{ Node node; //我们在这个自定义结构里的第一个元素,加上我们的结点结构的一个元素. int num; int val; }*abc; 还是起个好用的名字吧.
abc p=(abc)malloc(sizeof(_abc)); // 申请一个新对象
push(bgd,p); //这样就可以压入队列了
pop(bgd) ; //这样就可以弹出了,更简单