记录一些认为不错的数据结构程序算法

逆转链表:
#include<stdio.h>
#include<stdlib.h>
typedef struct nod
{
	int data;
	struct nod* next;
}nod;

typedef struct list
{
	nod* top;
	nod* last;
	int cnt;
}list;

list* create()
{
	list* p = (list*)malloc(sizeof(list));
	p->top = NULL;
	p->last = NULL;
	p->cnt = 0;
	return p;
}
nod* createnod(int data)
{
	nod* p = (nod*)malloc(sizeof(nod));
	p->data = data;
	p->next = NULL;
	return p;
}
int full(list* ps)
{
	return 0;
}
int empty(list* ps)
{
	return ps->cnt == 0;
}
void pushead(list* ps, int data)
{
	if (full(ps) == 0)
	{
		nod* p = createnod(data);
		if (ps->top == NULL)
		{
			ps->top = p;
			ps->last = p;
		}
		else
		{
			p->next = ps->top;
			ps->top = p;

		}
		ps->cnt++;
	}
}

void travel(list* ps)
{
	nod* p = ps->top;
	printf("目前元素有:");
	int i;
	for (i = 0; i<ps->cnt; i++)
	{
		printf("%d ", p->data);
		p = p->next;
	}
	p = NULL;
}
void reversenod(nod* p)  //先将p指到倒数第二个节点位置,主要利用递归,可以将指针p一直向上移动
{
	if (p->next != NULL)
	{
		reversenod(p->next);//递归!
		p->next->next = p;
		p->next = NULL;  //主要为了在头结点的时候使用
	}
}
void reverse(list* ps)
{
	nod* p = ps->top;
	reversenod(p);
	ps->top = ps->last; //将链表的头结点,尾节点位置重新分配好
	ps->last = p;
}
void main()
{
	int i;
	list* ps = create(); //创建一个空链表
	for (i = 0; i<5; i++)
		pushead(ps, i); //在链表中放五个节点
	travel(ps); //遍历链表中所有元素 打印出来
	reverse(ps);//逆转链表 重点
	travel(ps);

}

本人在写reverse()程序时的代码:
    多用了一个loc()函数,确定每一个节点的位置;利用for()将p指向倒数第二个节点,程序不简短。
nod* loc(list* ps,int loc)
{
	nod* p=ps->top;
	int i;
	if(loc==0)
		p=NULL;
	else
	{
		for(i=0;i<loc-1;i++)
		{
		p=p->next;
		}
	
	}
	return p;
}
reverse(list* ps)
{
	int i;
	nod* p=ps->last;
	for(i=0;i<ps->cnt;i++)
	{
	p->next=loc(ps,4-i);
	p=p->next;
	}
	ps->top=p;
	p=NULL;
}

二叉树的增加节点以及清除节点:主要利用了二级指针,就像当你将一个值传入一个局部函数,但不仅仅是利用这个值而是想要改变这个值的时候,要用到一级指针,当你想要改变一个值的地址时,要用到二级指针。
  二叉树的主要思想也是递归。
#include<stdio.h>
#include<stdlib.h>
typedef struct nod
{
	int data;
	struct nod* left;
	struct nod* right;
}nod;
typedef struct tree
{
	nod* root;
	int cnt;
}tree;

void insert_nod(nod** root, nod* pn)
{
	if (*root == NULL)             //每次递归都是将左右节点的地址传进来,而如果左右节点的地址是NULL,我们本意是想要改变这个值,因此不能直接传地址,而是要传地址的地址,即二级指针
		*root = pn;					
	if (pn->data>(*root)->data)
		insert_nod((&(*root)->right), pn);
	if (pn->data<(*root)->data)
		insert_nod((&(*root)->left), pn);
}
void insert(tree* tree, int data)
{
	nod* pn = (nod*)malloc(sizeof(nod));
	pn->data = data;
	pn->left = pn->right = NULL;
	insert_nod(&tree->root, pn);
	tree->cnt++;
}

void tree_nod(nod* root)
{
	if (root->left != NULL)
		tree_nod(root->left);
	printf("%d  ", root->data);
	if (root->right != NULL)
		tree_nod(root->right);
}
void travel(tree* tree)
{
	if (tree->root == NULL)
		printf("为空");
	else
		tree_nod(tree->root);
}
void clear_nod(nod** nod)
{
	if (*nod != NULL)
	{
		clear_nod(&(*nod)->left);
		clear_nod(&(*nod)->right);//确保左右都已经清理完毕
		free(*nod);
		*nod = NULL;  
	}
}
void clear(tree* tree)
{
	if (tree->root != NULL)
		clear_nod(&tree->root);
	tree->cnt = 0;
}
void main()
{
	tree tree;
	tree.root = NULL;
	tree.cnt = 0;
	int i;
	int arr[10] = { 60, 50, 20, 80, 70, 90, 10, 30, 40 };
	for (i = 0; i<10; i++)
		insert(&tree, arr[i]);
	travel(&tree);
	clear(&tree);
	travel(&tree);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值