2022 C语言数据结构总结浅浅入门(4)双向链表以及堆栈

上次我们讲了单向链表,那么这次我们将讲双向链表。

双向链表 有  一个数据域
                     两个指针域:  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");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值