一、顺序表
使用数组实现
优点:查找快,可以使用下标定位
缺点:增加、删除慢,之后的所有元素需要移动
结构体定义方式1:
需要malloc创建数组
typedef struct seqlist{
//数组指针,使用malloc动态创建堆上的数组
data_t *buf;
//数组长度
int maxLen;
//list后元素的位置
int last;
}seqlist_t;
结构体定义方式2:
这种方式可以使用定义变量的方式创建结构体,分配在栈上
也可以用malloc创建,分配在堆上
在malloc创建结构体或者定义变量时,系统根据结构体内元素的顺序,自动赋值对应的内存地址以初始化
typedef struct seqlist{
data_t buf[N];
int maxLen;
int last;
}seqlist_t;
常用方法:
//创建
seqlist_t *create_seqList(int size){
seqlist_t *l = (seqlist_t *)malloc(sizeof(seqlist_t));
l->buf = (data_t *)malloc(sizeof(data_t) * size);
l->maxLen = size;
l->last = -1;
}
//清空
void clear_seqlist(seqlist_t *l);
//判满
int is_full_seqlist(seqlist_t *l);
//判空
int is_empty_seqlist(seqlist_t *l);
//打印
void show_seqlist(seqlist_t *l);
//插入
int insert_seqlist(seqlist_t *l, int pos, data_t num);
//删除
data_t delete_seqlist(seqlist_t *l, int pos);
//定位
int index_of_seqlist(seqlist_t *l, data_t target);
//反转
void reverse_seqlist(seqlist_t *l){
int i = 0;
while(i < (l->last + 1)/2){
l->buf[i] ^= l->buf[l->last - i];
l->buf[l->last - i] ^= l->buf[i];
l->buf[i] ^= l->buf[l->last - i];
i++;
}
}
二、链表
使用指针将各个节点连接实现
优点:增加、删除快,直接改变指针的指向即可
缺点:查找慢,只能遍历
结构体定义方式:
typedef struct link_node{
//节点数据
data_t data;
//下个节点指针
struct link_node * next;
}linknode_t;
常用方法:
//创建
linklist_t create_linklist(){
//创建链表头,不存放数据
linklist_t l = (linklist_t)malloc(sizeof(linklist_t));
}
//判空
int is_empty_linklist(linklist_t l);
//打印
void show_linklist(linklist_t l);
//插入
int insert_linklist(linklist_t l, int pos, data_t data){
//malloc创建节点
}
//删除
int delete_linklist_node(linklist_t l, data_t data){
//解链
//free
}
//反转
void reverse_linklist(linklist_t l){
linknode_t *p = l->next;
l->next = NULL;
linknode_t *q;
while(p){
q = p->next;
p->next = l->next;
l->next = p;
p = q;
}
}
三、顺序栈
使用数组实现
依次往数组中添加元素,使用top标记后加入的元素的位置作为栈顶,出栈的时候再按照数组逆序取出
结构体定义方式1:
需要malloc创建数组
typedef struct node_t{
//数组指针
data_t *data;
//数组长度
int maxlen;
//栈顶位置
int top;
}arrstack_t;
结构体定义方式2:
typedef struct node_t{
data_t buf[N];
int maxLen;
int top;
}seqlist_t;
常用方法:
//创建
arrstack_t *create_stack(int len){
arrstack_t *stack = (arrstack_t *)malloc(sizeof(arrstack_t));
stack->data = (data_t *)malloc(sizeof(data_t) * len);
stack->maxlen = len;
stack->top = -1;
return stack;
}
//清空
int clear_stack(arrstack_t *s);
//判空
int is_empty_stack(arrstack_t *s);
//判满
int is_full_stack(arrstack_t *s);
//出栈
data_t pop_stack(arrstack_t *s);
//入栈
int push_stack(arrstack_t *s, data_t data);
//取栈首元素,不出栈
data_t get_top_stack(arrstack_t *s);
//打印
void show_stack(arrstack_t *s);
四、链式栈
使用链表实现
将链表第一个节点作为栈顶,每次都是从头部插入,出栈也是从头部弹出
结构体定义方式:
//链表节点结构体
typedef struct node_t{
data_t data;
struct node_t *next;
}stacknode_t;
//表示栈的结构体,为了方便像顺序栈一样操作,top始终指向链表第一个节点,表示栈顶
//也可以只定义一个结构体,定义一个头节点,使用头插法实现,这个只是个人习惯
typedef struct node_stack{
int len;
stacknode_t *top;
}linkstack_t;
常用方法:
//创建
linkstack_t *create_stack(){
linkstack_t *linkstack = (linkstack_t *)malloc(sizeof(linkstack_t));
linkstack->len = 0;
linkstack->top = NULL;
return linkstack;
}
//清空
int clear_stack(linkstack_t *s){
while(s->top){
stacknode_t *node = s->top;
s->top = node->next;
free(node);
node = NULL;
}
}
//判空
int is_empty_stack(linkstack_t *s);
//入栈
int push_stack(linkstack_t *s, data_t data){
stacknode_t *node = (stacknode_t *)malloc(sizeof(stacknode_t));
node->data = data;
node->next = NULL;
node->next = s->top;
s->top = node;
s->len++;
}
//出栈
int pop_stack(linkstack_t *s){
stacknode_t *node = s->top;
s->top = node->next;
s->len--;
data_t data = node->data;
free(node);
node = NULL;
}
//取栈首元素,不出栈
int get_top(linkstack_t *s);
//打印
void show_stack(linkstack_t *s);
五、链式队列
使用链表实现,定义一个front头指针,指向第一个元素前一个位置,定义一个rear尾指针,指向后一个元素位置
结构体定义方式:
//链表节点结构体
typedef struct node_t{
int data;
struct node_t *next;
}nodequeue_t, *linklist_t;
//表示队列的结构体
typedef struct{
linklist_t front, rear;
}linkqueue_t;
常用方法:
//创建
linkqueue_t *create_link_queue(){
//创建表示队列的结构体
linkqueue_t *lq = (linkqueue_t *)malloc(sizeof(linkqueue_t));
//创建链表的头节点,不存放数据
nodequeue_t *nq = (nodequeue_t *)malloc(sizeof(nodequeue_t));
nq->next = NULL;
lq->front = lq->rear = nq;
return lq;
}
//清空
int clear_queue(linkqueue_t *lq){
while(!is_empty_queue(lq)){
nodequeue_t *delnode = lq->front->next;
//判断队头的下一个是否是队尾,需要把rear指向链表头节点
if(lq->front->next == lq->rear){
lq->rear = lq->front;
}
lq->front->next = delnode->next;
free(delnode);
delnode= NULL;
}
}
//判空
int is_empty_queue(linkqueue_t *lq){
return lq->front == lq->rear;
}
//入队
int in_link_queue(linkqueue_t *lq, int data);
//出队
int out_link_queue(linkqueue_t *lq){
nodequeue_t *out_node = lq->front->next;
//每次都需要判断队头的下一个是否是队尾,需要把rear指向链表头节点
if(lq->rear == lq->front->next){
lq->rear = lq->front;
}
lq->front->next = out_node->next;
int ret = out_node->data;
free(out_node);
out_node = NULL;
}
//打印
void show_link_queue(linkqueue_t *lq);
六、顺序队列
使用数组实现,使用伪溢出的方式将数组当成一个循环链表
结构体定义方式1:
使用数组指针,需要malloc创建数组
typedef struct node_t{
data_t *data;
int max_size;
int front, rear;
}arrqueue_t;
结构体定义方式2:
typedef struct node_t{
data_t data[N];
int max_size;
int front, rear;
}arrqueue_t;
常用方法:
//创建
arrqueue_t *create_arrqueue(int size){
arrqueue_t *q = (arrqueue_t *)malloc(sizeof(arrqueue_t));
q->data = (data_t *)malloc(sizeof(data_t) * size);
q->max_size = size;
q->front = q->rear = size - 1;
return q;
}
//判空
int is_full_queue(arrqueue_t *q){
if(((q->rear + 1)%q->max_size) == q->front){
return 1;
}
}
//判满
int is_empty_queue(arrqueue_t *q){
return q->rear == q->front;
}
//入队
int in_queue(arrqueue_t *q, data_t data){
q->rear = (q->rear + 1)%q->max_size;
q->data[q->rear] = data;
}
//出队
int out_queue(arrqueue_t *q){
q->front = (q->front + 1)%q->max_size;
return q->data[q->front];
}
//清空
int clear_queue(arrqueue_t *q);
//打印
void show_arrqueue(arrqueue_t *q){
/*
int temp = q->front;
do{
temp = (temp + 1)%N;
printf("%d\n",q->data[temp]);
}while(temp!= q->rear);
*/
/*
int i;
for(i = (q->front + 1)%N; i != (q->rear + 1)%N; i = (i + 1)%N){
printf("%d\n",q->data[i]);
}
*/
int i = 0;
int size = ((q->max_size - q->front) + q->rear)%q->max_size;
while(i < size){
int index = (q->front + 1 + i)%q->max_size;
printf("queue[%d] = %d\n", index, q->data[index]);
i = (i + 1)%q->max_size;
}
}
七、二叉树
结构体定义方式:
typedef struct tree{
int data;
struct tree *lchild, *rchild;
}tree_t;
常用方法:
//创建指定节点数的完全二叉树
tree_t *create_totol_tree(int i, int num){
tree_t *t = (tree_t *)malloc(sizeof(tree_t));
t->data = i;
if(2 * i <= num){
t->lchild = create_totol_tree(2 * i, num);
}else{
t->lchild = NULL;
}
if(2 * i + 1 < num){
t->rchild = create_totol_tree(2 * i + 1, num);
}else{
t->rchild = NULL;
}
return t;
}
//递归方式创建二叉树
tree_t *create_tree(){
char ch;
tree_t *t;
scanf("%c", &ch);
if('#' != ch){
t = (tree_t *)malloc(sizeof(tree_t));
t->data = ch;
t->lchild = create_tree();
t->rchild = create_tree();
return t;
}else{
return NULL;
}
}
//递归方式-前序遍历二叉树
void pr_show_tree(tree_t *t){
if(NULL == t){
return;
}
printf("%c", t->data);
pr_show_tree(t->lchild);
pr_show_tree(t->rchild);
}
//递归方式-中序遍历二叉树
void mid_show_tree(tree_t *t){
if(NULL == t){
return;
}
mid_show_tree(t->lchild);
printf("%c", t->data);
mid_show_tree(t->rchild);
}
//递归方式-后序遍历二叉树
void re_show_tree(tree_t *t){
if(NULL == t){
return;
}
re_show_tree(t->lchild);
re_show_tree(t->rchild);
printf("%c", t->data);
}