数据结构学习总结2

1. 栈操作

        (1)栈特点:  先进后出, 后进先出
        (2)实现:   顺序表    链表
        (3)基础概念:   
                   栈底
                   栈底:  入栈、出栈都是从栈底操作的

                   ps:  栈不可以在中间做插入或者删除的操作

       

        (1)栈的初始化

struct stack
{
	int *space; //栈空间的起始地址
	int  len;   //总的数据个数
	int  count; //实际存储数据的个数
};

//栈的初始化
void  stack_init(struct stack *ps, int n)
{
	ps->space = (int *)malloc(sizeof(int)*n);
    assert((ps->space) != NULL);

	ps->len = n;

	ps->count = 0;
	return ;
}



//栈的大小(使用的元素个数)

int stack_size(struct stack s)
{
	return s.count;
}


//判断栈是否为空
bool  is_empty(struct stack s)
{
	if(s.count == 0)
	{
		return true;
	}
	else
	{
		return false;
	}
}



//判断栈是否已满
bool  is_full(struct stack s)
{
	if(s.count == s.len)
	{
		return true;
	}
	else
	{
		return false;
	}
}

        (2)入栈

//入栈
//成功返回0    失败返回-1
int stack_push(struct stack *ps, int  data)
{
	//判断栈是否已满
	if(is_full(*ps))
	{
		printf("栈已满,入栈失败!\n");
		return -1;
	}

	ps->space[ps->count] = data;

	(ps->count) ++;
	return 0;
}

               (3) 出栈

//出栈
int stack_pop(struct stack *ps, int *presult)
{
	//判断栈是否为空
	if(is_empty(*ps))
	{
		printf("栈为空,出栈失败!\n");
		return  -1;
	}


	if(presult != NULL)
	{
		*presult = ps->space[(ps->count)-1];
	}


	(ps->count) --;

	return 0;
}

        (3)主函数验证:

int main()
{
	struct  stack   s1;
    
	stack_init(&s1, 5);

	stack_push(&s1, 1);
	stack_push(&s1, 2);
	stack_push(&s1, 3);
	stack_push(&s1, 4);
	stack_push(&s1, 5);


    int data;
	stack_pop(&s1,&data);
	printf("data: %d\n", data);
	stack_pop(&s1,&data);
	printf("data: %d\n", data);
	stack_pop(&s1,&data);
	printf("data: %d\n", data);
	stack_pop(&s1,&data);
	printf("data: %d\n", data);
	stack_pop(&s1,&data);
	printf("data: %d\n", data);
	
	stack_pop(&s1,&data);
	return 0;
}

2. 队列

        (1)特点:  先进先 出, 后进后出

        (2)  实现:   顺序表     链式

        (3)   队头   队尾

        ps:  不允许在中间做插入或者删除的操作!

        (1)队列初始化

//表示队列节点的类型
struct node
{
	int data;
	struct node *next;
};



//表示队列的基本信息
struct queue
{
	int  len; //设置队列的总长度
	int  count; //当前节点的个数
	struct node *first; //保存第一个节点的地址
	struct node *tail;  //保存最后一个节点的地址
};

//初始化
void queue_init(struct queue *pq, int n)
{
	pq->len = n;
	pq->count = 0;
	pq->first = NULL;
	pq->tail = NULL;
	return ;
}



//判断队列是否已满

bool is_full(struct queue q)
{
	if(q.count == q.len)
	{
		return true;
	}
	else
	{
		return false;
	}
}

//判断队列是否为空
bool is_empty(struct queue q)
{
	if(q.count == 0)
	{
		return true;
	}
	else
	{
		return false;
	}
}

        (2)入队

//入队 (尾部追加)
//成功返回0   失败-1

int  queue_push(struct queue *pq, int data) 
{
	//判断队列是否已满
	if(is_full(*pq))
	{
		printf("队列已满,入队失败!\n");
		return -1;
	}

	//正确流程
	struct node *pnew = NULL;
	pnew = (struct node *)malloc(sizeof(struct node));
	assert(pnew!=NULL);
	pnew->data = data;
	pnew->next = NULL;

	if(pq->first == NULL)  //空链表
	{
		pq->first = pnew;
		pq->tail = pnew;
	}
	else //非空链表  让最后一个节点的next保存新的节点地址 
	{
		pq->tail->next = pnew;
		pq->tail = pnew;
	}

	pq->count ++;
	return 0;
}

        (3)出队

//出队 (头部删除)
int queue_pop(struct queue *pq, int *presult)
{
	//判断队列是否为空
	if(is_empty(*pq))
	{
		printf("队列为空 ,出队失败!\n");
		return -1;
	}

	//正确流程
	struct node *pdel = NULL;
	
	//1)保存第一个节点的地址,将第一个节点从链表中移下来
	pdel = pq->first;
	pq->first = pq->first->next;

	// 2)返回出队的数据
	if(presult != NULL)
	{
		*presult = pdel->data;
	}

	//3)释放内存
	free(pdel);

	//4)判断是否是空链表
	if(pq->first == NULL) //设置tail的值
	{
		pq->tail = NULL;
	}

	//5)设置count值
	pq->count --;


	return  0;
}

        (4)主函数验证

int main()
{
	struct queue   q1; 

	queue_init(&q1, 5);

	queue_push(&q1, 1);
	queue_push(&q1, 2);
	queue_push(&q1, 3);
	queue_push(&q1, 4);
	queue_push(&q1, 5);

    int data;
	queue_pop(&q1,&data);
	printf("data: %d\n", data);
	queue_pop(&q1,&data);
	printf("data: %d\n", data);
	queue_pop(&q1,&data);
	printf("data: %d\n", data);
	queue_pop(&q1,&data);
	printf("data: %d\n", data);
	queue_pop(&q1,&data);
	printf("data: %d\n", data);
	
	queue_pop(&q1,&data);
	return 0;
}

3. 二叉树

      

完全二叉树

  • 若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
  • 一维数组可以作为完全二叉树的存储结构,堆排序使用的数据结构就是完全二叉树

满二叉树

          国际标准定义是除了叶结点外每一个结点都有左右子结点的二叉树

        (1)创建二叉树

//表示节点的类型
struct node
{
	int data;
	struct node *left;
	struct node *right;
};


struct node* create_tree()
{
	struct  node *root = NULL;
	struct  node *pnew = NULL;
	
	int x;
	scanf("%d", &x);
	while(getchar() != '\n');

	while(x)
	{
		//1、创建新的节点,并且赋值
		pnew = (struct node*)malloc(sizeof(struct node));
		assert(pnew!=NULL);
		pnew->data = x;
		pnew->left = NULL;
		pnew->right = NULL;

		//2、加入有序二叉树
		if(NULL == root)
		{
			root = pnew;
		}
		else
		{
			struct node *p = root;
            struct node *q = NULL;
			while(p != NULL)
			{
				q = p;
				if(pnew->data < p->data)
				{
					p = p->left;
				}
				else
				{
					p = p->right;
				}
			}

			if(pnew->data < q->data)
			{
				q->left = pnew;
			}
			else
			{
				q->right = pnew;
			}
		}

		scanf("%d", &x);
		while(getchar()!='\n');
	}
	return root;
}

        (2)遍历二叉树

#if   0
先序遍历
先访问根节点
然后先序遍历左子树
最后先序遍历右子树
#endif

void  pre_print(struct node *root)
{
	if(root != NULL)
	{
		printf("%d ", root->data);
		pre_print(root->left);
		pre_print(root->right);
	}
}


#if   0
中序遍历
先中序遍历左子树
再访问根节点
最后中序遍历右子树
#endif
void   mid_print(struct node *root)
{
	if(root != NULL)
	{
		mid_print(root->left);
		printf("%d ", root->data);
		mid_print(root->right);
	}
}


#if   0
后序遍历
先后序遍历左子树
再后序遍历右子树
最后访问根节点
#endif
void   tail_print(struct node *root)
{
	if(root != NULL)
	{
		tail->print(root->left);
		tail->print(root->right);
		printf("%d", root->data);
	}
}

        (2)主函数

int main()
{
	struct node *root = NULL;
	root = create_tree();

	pre_print(root);
	printf("\n");
	return 0;
}

4. 哈希表

        hash函数就是根据key计算出应该存储地址的位置,而哈希表是基于哈希函数建立的一种查找表

        (1)除留余数法

                        H(key)=key % p 

5. 排序

        快速排序

                在一个无序数组中取一个数key,每一趟排序的最终目的是:让key的左边的所有数小于key,key的右边都大于key(假设排升序)

        代码实现

#include <stdio.h>



int find_pos(int a[], int low, int high)
{
	int key = a[low];

	while(low<high)
	{
		while(low<high && a[high]>=key)
		{
			high --;
		}

		a[low] = a[high];

		while(low<high && a[low] <= key)
		{
			low ++;
		}
		a[low] = a[high];
	}
	a[low] = key;
	return low;
}




void  quick_sort(int a[], int low, int high)
{
	if(low < high)
	{
		int pos = find_pos(a, low, high);
		quick_sort(a, low, pos-1);
		quick_sort(a, pos+1,high);
	}
}


int main()
{
	int a[5] = {9, 8, 2, 5, 1};


	quick_sort(a, 0, 4);

	for(int i=0; i<5; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值