2015.2.8
星期二,晴天node
棧的數組操做:算法
棧的特色:先進後出,後進先出。數組
用數組的方式實現:首先須要建立一個結構體,在結構體裏面包括數據指針、指向棧頂的」指針「和標記棧的大小的一個變量。數據指針是指向必定大小的數組的首地址。結構體和這個
數組夠成一個完整的棧。數據結構
1.在建立棧的操做中,主要就是建立這個結構體和這個數組,並對其進行必定的初始化,這個操做和鏈表的建立比較相似,初始化的語句:
stack->max_depth = max_depth; //說明棧的大小
stack->pop = -1; //說明如今的棧是一個空棧函數
#include <stdio.h>
#include <stdlib.h>指針
typedef int data_t;隊列
typedef struct stack{ //建立一個結構體
data_t *data;
int pop;
int max_depth;
} sqstack_t;內存
sqsatck_t * Create_Empty_Sqstack(int max_depth)
{
sqstack_t *stack;
stack = (sqstack_t *)malloc(sizeof(sqstack_t)); //先建立棧
if(stack)
{
stack->data = (data_t *)malloc(sizeof(data_t) * max_depth); //建立數組,注意數組大小的算法
if(stack->data == NULL)
{
free(stack);
return NULL;
}
}rem
stack->max_depth = max_depth; //對棧的初始化操做
stack->pop = -1;io
return stack;
}
void Destory_Sqstack(sqstack_t stack) //銷燬一個棧,應爲不是鏈表,因此不須要一個個釋放數組中每一個數據的內存,將指向內存的指針釋放就好了
{
if(stack)
{
if(stack->data)
{
free(stack->data); //釋放數組
stack->data = NULL;
}
free(stack); //釋放結構體,此時整個棧就銷燬了
stack = NULL;
return ;
}
}
void Clear_Sqstack(sqstack_t stack) //清空棧,一樣不不用一個個清除,直接對棧頂指針進行操做就好了
{
if(stack == NULL)
{
return -1;
}
stack->pop = -1; //將棧頂指針指向空,代表此時的棧已經清空
return;
}
int Empty_Sqstack(sqstack_t stack) //判斷棧是否爲空,只須要查尋棧頂指針就好了
{
if(stack == NULL)
{
return -1;
}
return(stack->pop == -1 ? 1 : 0); //判斷棧頂指針是否指向空
}
int Full_Sqstack(sqstack_t stack) //判斷棧是否已經滿了,只須要查尋棧頂指針是否和棧的長度長度相等就好了
{
if(stack == NULL)
{
return -1;
}
return(stack->pop + 1 == max_depth ? 1 : 0); // 查尋棧頂指針是否和棧的長度長度相等
}
int Push_Sqstack(sqstack_t stack,data_t x) //主要的操做來了,壓棧,應爲棧頂指針始終指向棧頂的數據,因此,壓入數據以前須要移動棧頂指針,\
{ 不然會覆蓋原先的數據
if(Full_Sqstack(stack))
{
return -1;
}
stack->pop++; //移動棧頂指針
stack->data[stack->pop] = x; //壓榨
return 0;
}
int Pop_Sqstack(sqstack_t stack,data_t *x) //也是主要操做,出棧,應爲棧頂指針始終指向棧頂的數據,在出棧以前不須要對棧頂指針進行操做,可是\
{ 出棧後須要將修改棧頂指針的位置,以便下次對棧進行操做
if(Empty_Sqstack(stack))
{
return -1;
}
if(x)
{
*x = stack->data[stack->pop]; //出棧
stack->pop--; //修改棧頂指針
return 0;
}
else
{
return -1;
}
}
int Get_Sqstack_Pop(sqstack_t stack,data_t *x) //取得棧頂的數據,這個功能只是取的棧頂的數據,因此,沒有修改棧頂指針
{
if(Empty_Sqstack(stack))
{
return -1;
}
if(x)
{
*x = stack->data[stack->pop];
return 0;
}
else
{
return -1;
}
}
棧的鏈表操做:
鏈表實現的方式和單鏈表的不少操做都有類似之處,特別是在建立,初始化,清空棧的時候須要一個個清除鏈表中的數據,出棧時的銷燬動做等都很相似
#include <stdio.h>
#include <stdlib.h>
typedef int data_t;
typedef struct Lstack{ //建立一個簡單的結構體
data_t data;
struct Lstack *next;
}linkstack_t;
linkstack_t * Create_Empty_Linkstack(int max_depth)
{
linkstack_t *stack;
stack = (linkstack_t *)malloc(sizeof(linkstack_t));
if(stack)
{
stack->next = NULL; //初始化棧頂,也就是表頭
}
return stack;
}
void Clear_Linkstack(linkstack_t stack)
{
linkstack_t *node;
if(stack == NULL)
{
return -1;
}
if(NULL != stack->next) //清空操做,一個個清空內存,用到了標記指針
{
node = stack->next;
stack->next = node->next;
free(node);
}
return;
}
void Destory_Linkstack(linkstack_t stack) //銷燬操做,大原則:先清空,後銷燬(呵呵,貌似很環保)
{
if(stack)
{
Clear_Linkstack(stack);
free(stack);
stack = NULL;
}
}
int Empty_Linkstack(linkstack_t stack) //判斷是否爲空,只須要查尋表頭指針就好了(備註一下,這裏沒有寫判斷棧滿的函數,應爲鏈表能夠不斷生長,全部不會滿)
{
if(stack )
{
return (stack->next == NULL ? 1 : 0); //查尋表頭指針是否指向空
}
else
{
return -1;
}
}
int Push_Linkstack(linkstack_t stack,data_t x) //壓棧操做,始終將數據放到表頭所指向的位置就好了,很簡單
{
linkstack_t *node;
if(stack == NULL)
{
return -1;
}
node = (linkstack_t *)malloc(sizeof(linkstack_t));
if(node == NULL)
{
return -1;
}
node->data = x;
node->next = stack->next; //插入的操做
stack->next = node;
return 0;
}
int Pop_Linkstack(linkstaxk_t stack,data_t *x) //出棧的操做,出棧前須要判斷棧是否空了,以避免誤操做,出棧後須要將棧頂的那個數據釋放掉,因此,\
{ 須要有個標誌指針標記處須要釋放的結構體,
linkstack_t *node;
if(stack == NULL || stack->next == NULL )
{
return -1;
}
node = stack->next; //對標記指針的操做
stack->next = node->next;
if(x)
{
*x = node->data;
}
free(node);
return 0;
}
int Get_Linkstack_Pop(linkstack_t stack,data_t *x) //取得棧頂的數據,這個時候只是取,不釋放
{
if(stack == NULL || stack->next == NULL)
{
return -1;
}
*x = stack->next->data;
return 0;
}
隊列的數組實現:
隊列的特色:先進先出,後進後出
數組的方式實現:首先須要明確數組長度,這樣標誌隊首和對尾的指針就能操做這個數組了,這裏利用的是循環數組的方式,因此實際的數組長度等於存放的數據長度+1;
這裏用到的兩個重要的公式,分別對隊首和隊尾操做的:
queue->rear= (queue->rear+ 1) % N; //取隊首的數據
queue->rear= (queue->rear+ 1) % N; //向隊尾插入數據
queue->front == queue->rear //空棧的判斷條件
queue->front == (queue->rear + 1) % N //滿棧的判斷條件
#include <stdio.h>
#include <stdlib.h>
#define FIFO_LEN 9 //存放數據的個數
#define N (FIFO_LEN + 1) //數組的實際長度
typedef int data_t;
typedef struct{
data_t data[N];
int front;
int rear;
}sequeue_t;
sequeue_t *Create_Empty_Queue() //建立一個空隊列,這時須要的初始化操做是將隊首和隊尾的指針都指向標記位,空棧是0
{
sequeue_t *queue;
queue = (sequeue_t *)malloc(sizeof(sequeue_t));
if(queue == NULL)
{
return NULL;
}
queue->front = queue->rear = 0; //初始化隊首和隊尾指針
return queue;
}
void Destory_Queue(sequeue_t *queue) //銷燬隊列,直接釋放結構體指針指向的內存就好了
{
if(queue)
{
free(queue);
}
}
int Empty_Queue(sequeue_t *queue) //判斷隊列是否爲空,主要就是查尋隊首和隊尾的指針並進行比較
{
if(queue == NULL)
{
return -1;
}
return (queue->front == queue->rear ? 1 : 0); //空隊列的比較比較公式
}
int Full_Queue(sequeue_t *queue) //判斷隊列是否已滿
{
if(queue == NULL)
{
return -1;
}
return ((queue->rear + 1) % N == queue->front ? 1 : 0); //滿隊列的比較公式
}
int Clear_Queue(sequeue_t *queue) //清空隊列的操做,主要就是講隊首和隊尾的指針指向空棧的標誌位就行了
{
if(queue == NULL)
{
return -1;
}
queue->front = queue->rear = 0; //清空操做,和初始化同樣
return 0;
}
int En_Queue(sequeue_t *queue,data_t x) //向隊列的尾插入一個數組,首先須要判斷隊列是否已滿,而後在根據條件插入數據
{
if(queue == NULL || Full_Queue(queue) == 1)
{
return -1;
}
queue->rear= (queue->rear+ 1) % N; //將隊尾指針修改成須要插入數據的位置,而後再插入數據
queue->data[queue->rear] = x;
return 0;
}
int De_Queue(sequeue_t *queue, data_t *x) //去出對首的數據,首先須要判空,由於數據時存放在數組裏,後面插入數據的時候能夠直接覆蓋,因此不須要進行清除操做
{
if(queue == NULL || Empty_Queue(queue)== 1)
{
return -1;
}
queue->front= (queue->front+ 1) % N; //修改隊首指針,使其指向將要獲取的數據
if(x)
{
*x = queue->data[queue->front] //取數據
}
return 0;
}
鏈表實現的隊列:
鏈表實現隊列的操做:這裏將隊首和隊尾的指針封裝在一個結構體裏面,操做這個兩個指針的方式和稍有不一樣,特別是在建立空隊列的時候,不是對鏈表的數據結構體進行操做,
而是對這兩個指針進行相應的操做,多體會體會。
#include <stdio.h>
#include <stdlib.h>
typedef int data_t;
typedef struct Lqueue{
data_t data;
struct Lqueue *next;
}queuenode_t,*queuelist_t;
typedef struct{
queuelist_t front,rear;
}linkqueue;
queue_link *Create_Empty_Linkqueue() //建立空隊列:建立封裝了指針的結構體,而後對這個兩個指針進行初始化操做
{
linkqueue *queue;
queue = (linkqueue *)malloc(sizeof(linkqueue)); //建立隊列的表頭
if(queue == NULL)
{
return NULL;
}
queue->rear = queue->front = NULL; //初始化表頭
return queue;
}
void Clear_Linkqueue(linkqueue *queue) //清空隊裏,鏈表實現的隊列須要一個個清空,這裏的的隊首指針始終指向第一個數據結構體
{
queuelist_t node_free;
if(queue == NULL)
{
return -1;
}
while(queue->front != NULL)
{
node_free = queue->front;
queue->front = node->free->next;
free(node_free);
}
return ;
}
void Destory_Linkqueue(sequeue_t * queue) //銷燬隊列:大原則,先清空,後銷燬
{
if(queue)
{
Clear_Linkqueue(queue);
free(queue);
}
}
int Empty_Linkqueue(linkqueue *queue) //判斷隊列是否爲空,只要查尋對首指針是否爲空就好了
{
if(queue == NULL)
{
return -1;
}
return(queue->front == NULL ? 1 : 0);
}
int En_Linkqueue(linkqueue *queue,data_t x) //向隊列中插入數據,此時分兩種狀況,須要判斷原先隊列中是否存在數據,而後根據不一樣的狀況進行不一樣的插入操做\
{ 這裏要注意:插入數據後須要相應的修改隊尾指針,第一次插入數據時還須要修改對首指針。
queuelist_t node_new;
if(queue == NULL)
{
return -1;
}
node_new = (queuelist_t)malloc(sizeof(queuenode_t));
if(node_new == NULL)
{
return -1;
}
node_new->data = x;
node_new->next = NULL;
if(queue->front == NULL) //隊列中原先沒有數據
{
queue->front = queue->rear = node_new;
}
else //隊列中原先已有數據
{
queue->rear->next = node_new; //插入數據到隊列尾
queue->rear = node_new; //修改隊尾指針,指向最後插入的數據
}
return 0;
}
int De_Linkqueue(linkqueue *queue,data_t *x) //從隊列中取數據:根據取數據後隊列是否爲空分爲兩種操做,分別修改隊首或者對首指針!!!
{
queuelist_t node_remove;
if(queue == NULL || queue->front == NULL)
{
return -1;
}
node_remove = queue->fornt;
queue->front = node_remove->next;
if(queue->front == NULL) //取完數據後隊列爲空隊列,須要修改對尾指針
{
queue->rear = NULL; //須要修改對尾指針
}
if(x)
{
*x = node_remove->data;
}
free(node_remove); return 0;}