上次我们讲了单向链表,那么这次我们将讲双向链表。
双向链表 有 一个数据域
两个指针域: 1) 指向前一个节点 (prev) 2) 指向后一个节点 ( next )
双向链表,可以向后走,也可以向前走, 速度更快
双向链表结构体如何定义?
typedef struct node
{
int data;
struct node_t *prev;
struct node_t *next;
}Node;
Node *init()
{
Node *head=(Node *)malloc(sizeof(struct node));//头节点申请地址
head->perv=NULL;
head->next=NULL;
head->data=0;
return head;
}
//插入新节点
int insert_node(Node *head,int pos,int val)
{
Node *h=head;
Node *p=(Node *)malloc(sizeof(struct node));//给新节点分配地址
p->data=val;
int i;
for(i=0;i<pos-1;i++)//循环到插入位置的前驱节点
h=h->next;
p->next=h->next; //新节点的后继指针等于前驱节点的后继指针
p->perv=h; //新节点的前驱指针指向前驱节点
if(h->next!=NULL) //如果初始前驱节点有后继节点
h->next->perv=p; //后继节点的前驱指针指向新节点
h->next=p; //前驱节点的后继指针指向新节点
printf("在第%d位插入%d\n",pos,val);
return 1;
}
//删除节点
int del_node(Node *head,int pos)
{
Node *h=head;
Node *q;
int i;
for(i=0;i<pos-1;i++)//道理与插入类似,可以自己思考一下
h=h->next;
q=h->next;
h->next->perv=NULL;
if(q->next!=NULL)
{
q->next->perv=h;
}
h->next=q->next;
free(q);//释放删除节点的空间
printf("删除第%d位节点\n",pos);
return 1;
}
//输出整个链表
void printf_all(Node *head)
{
while(head->next!=NULL)//链表末尾节点的后继指针为空
{
head=head->next;
printf("%-5d",head->data);
}
printf("\n");
}
int main()
{
//测试
Node *head=init();
insert_node(head,1,1);
printf_all(head);
insert_node(head,1,2);
printf_all(head);
insert_node(head,1,3);
printf_all(head);
del_node(head,1);
printf_all(head);
}
下面我们讲讲栈
栈(stack)
栈是只能在一端进行插入和删除操作的线性表(又称为堆栈)
栈的操作规则(后进先出LIFO last in first out) (或者FILO first in last out)
栈的典型应用(函数的执行过程)
栈: 栈顶(top)
栈顶 进行插入和删除操作
栈可以用数组来实现
实现栈练习
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int *data; //
int maxlen; //栈中最多存储的元素个数
int top; //栈顶
}stack_t; //stack
//创建空堆栈 返回指向栈的指针
stack_t *CreateEmptyStack(int len)
{ //1) 动态分配内存 2) top = 0 3) maxlen = len(不是必须的)
stack_t *p = malloc(sizeof(stack_t));
p->data = malloc(len * sizeof(int));
p->maxlen = len;
p->top = 0;
return p;
}
//判断栈是否为空( 空: 返回1 非空: 返回0)
int EmptyStack(stack_t *p)
{
if(p->top == 0)
return 1;
else
return 0;
}
//判断栈是否为满( 满: 返回1 非满: 返回0)
int FullStack(stack_t *p)
{
if(p->top == p->maxlen) //return p->top == p->maxlen;
return 1;
else
return 0;
}
//入栈 (返回值, 成功:0 失败:-1)
int pushStack(stack_t *p, int x)
{ //1) 判断是否满, 2) 存入数 3) top++
if(FullStack(p) == 1) //if(FullStack(p))
{
printf("stack full\n");
return -1;
}
p->data[p->top] = x;
p->top++;
return 0;
}
//出栈 (返回值, 成功: 有效数 失败: -1)
int popStack(stack_t *p)
{ //1) 判断是否空 2) top-- 3) 返回值
if(EmptyStack(p))
{
printf("stack empty\n");
return -1;
}
p->top--;
return p->data[p->top];
}
//清空栈
void clearStack(stack_t *p)
{
p->top = 0;
}
int main()
{
stack_t *p = CreateEmptyStack(5);
pushStack(p, 10);
pushStack(p, 20);
pushStack(p, 30);
pushStack(p, 40);
pushStack(p, 50);
pushStack(p, 60); //栈已经满,失败
printf("%d\n", popStack(p)); //50
printf("%d\n", popStack(p)); //40
printf("%d\n", popStack(p)); //30
printf("%d\n", popStack(p)); //20
printf("%d\n", popStack(p)); //10
printf("%d\n", popStack(p)); //栈已经空,失败
}
堆栈
只允许在一端(top)进行插入和删除的线性表叫堆栈(LIFO或者FILO)
堆栈有一个堆栈指针(top), 指向栈顶
1 空堆栈 top 初值为0 (上面的例子 top位置没存数据,将要存入数据的位置)
2 满堆栈 top 初值为-1 (top位置有数据)
例:
用栈实现将10进制数转换成2进制 输出
11 (1011)
11 % 2 = 1(入栈)
11 / 2 = 5
5 % 2 = 1(入栈)
5 / 2 = 2
2 % 2 = 0(入栈)
2 / 2 = 1
1 % 2 = 1(入栈)
1 / 2 = 0 结束
出栈,直到栈空为止
实现:
1) 创建一个栈 最多存入100个元素
2) 输入一个数
3) 循环 入栈
4) 循环出栈
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int *data; //
int maxlen; //栈中最多存储的元素个数
int top; //栈顶
}stack_t; //stack
//创建空堆栈 返回指向栈的指针
stack_t *CreateEmptyStack(int len)
{ //1) 动态分配内存 2) top = 0 3) maxlen = len(不是必须的)
stack_t *p = malloc(sizeof(stack_t));
p->data = malloc(len * sizeof(int));
p->maxlen = len;
p->top = 0;
return p;
}
//判断栈是否为空( 空: 返回1 非空: 返回0)
int EmptyStack(stack_t *p)
{
if(p->top == 0)
return 1;
else
return 0;
}
//判断栈是否为满( 满: 返回1 非满: 返回0)
int FullStack(stack_t *p)
{
if(p->top == p->maxlen) //return p->top == p->maxlen;
return 1;
else
return 0;
}
//入栈 (返回值, 成功:0 失败:-1)
int pushStack(stack_t *p, int x)
{ //1) 判断是否满, 2) 存入数 3) top++
if(FullStack(p) == 1) //if(FullStack(p))
{
printf("stack full\n");
return -1;
}
p->data[p->top] = x;
p->top++;
return 0;
}
//出栈 (返回值, 成功: 有效数 失败: -1)
int popStack(stack_t *p)
{ //1) 判断是否空 2) top-- 3) 返回值
if(EmptyStack(p))
{
printf("stack empty\n");
return -1;
}
p->top--;
return p->data[p->top];
}
//清空栈
void clearStack(stack_t *p)
{
p->top = 0;
}
int main()
{
stack_t *p = CreateEmptyStack(100);
int n;
scanf("%d", &n);
while(n != 0)
{
pushStack(p, n % 2);
n = n / 2;
}
while(!EmptyStack(p))
{
printf("%d", popStack(p));
}
printf("\n");
}