嵌入式入门学习笔记,遇到的问题以及心得体会!
DAY22
笔记:
一.链式栈的实现:
1.stack.h ----------------------------------------------------- 如下
#ifndef _STACK_H_
#define _STACK_H_
typedef int data_t;
typedef struct StackNode
{
data_t data;
struct StackNode *pNext;
}StackNode;
typedef struct Stack
{
StackNode *pHead;
int count;
}Stack;
enum STACK_OP
{
STACK_ERROR = -1,
STACK_EMPTY,
STACK_OK
};
//创建
Stack *createStack();
//入栈
int pushStack(Stack *pStack,data_t tData);
//出栈
int popStack(Stack *pStack,data_t *pData);
//销毁
void destroyStack(Stack **ppStack);
//判断是否为空
int isEmpty(Stack *pStack);
#endif
2.stack.c ----------------------------------------------------- 如下
#include <stdio.h>
#include "stack.h"
#include <stdlib.h>
#include <string.h>
//创建
Stack *createStack()
{
Stack *pStack = (Stack *)malloc(sizeof(Stack));
if(NULL == pStack)
{
return NULL;
}
pStack->pHead = NULL;
pStack->count = 0;
return pStack;
}
//入栈
int pushStack(Stack *pStack,data_t tData)
{
if(NULL == pStack)
{
return STACK_ERROR;
}
StackNode *pNode = (StackNode*)malloc(sizeof(StackNode));
memset(pNode,0,sizeof(StackNode));
pNode->data = tData;
if(NULL == pStack->pHead)
{
pStack->pHead = pNode;
pStack->count++;
return STACK_OK;
}
pNode->pNext = pStack->pHead;
pStack->pHead = pNode;
pStack->count++;
return STACK_OK;
}
//出栈
int popStack(Stack *pStack,data_t *pData)
{
if(NULL == pStack || NULL == pStack->pHead || NULL == pData)
{
return STACK_ERROR;
}
*pData = pStack->pHead->data;
if(1 == pStack->count)
{
free(pStack->pHead);
pStack->pHead = NULL;
pStack->count--;
return STACK_OK;
}
StackNode *pTemp = pStack->pHead;
pStack->pHead = pStack->pHead->pNext;
free(pTemp);
pTemp = NULL;
pStack->count--;
}
//销毁
void destroyStack(Stack **ppStack)
{
if(NULL == ppStack || NULL ==*ppStack || (*ppStack)->pHead)
{
return;
}
StackNode *pTemp = NULL;
while((*ppStack)->pHead != NULL)
{
pTemp = (*ppStack)->pHead;
(*ppStack)->pHead = (*ppStack)->pHead->pNext;
free(pTemp);
}
pTemp = NULL;
free(*ppStack);
*ppStack = NULL;
}
//判断是否为空栈
int isEmpty(Stack *pStack)
{
if(NULL == pStack)
{
return STACK_ERROR;
}
if(NULL == pStack->pHead)
{
return STACK_EMPTY;
}
return STACK_OK;
}
3.main.c ----------------------------------------------------- 如下
#include <stdio.h>
#include "stack.h"
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
Stack *pStack = createStack();
if(NULL == pStack)
{
return -1;
}
data_t data;
int i;
for(i=0;i<5;i++)
{
pushStack(pStack,i);
}
while(STACK_EMPTY != isEmpty(pStack))
{
popStack(pStack,&data);
printf("%d ",data);
}
printf("\n");
destroyStack(&pStack);
return 0;
}
二.顺序队列的实现
1.seqqueue.h ----------------------------------------------------- 如下
#ifndef _QUEUE_H_
#define _QUEUE_H_
#define SIZE 5
typedef int data_t;
typedef struct Queue
{
data_t data[SIZE];
int iFront;
int iRear;
int count;
}Queue;
enum QUEUE_OP
{
QUEUE_ERR = -1,
QUEUE_OK,
QUEUE_EMPTY,
QUEUE_FULL
};
Queue *CreateQueue();
int enQueue(Queue *pQueue, data_t tData);
int deQueue(Queue *pQueue, data_t *pData);
int isEmpty(Queue *pQueue);
int isFull(Queue *pQueue);
void destroyQueue(Queue **ppQueue);
#endif
2.seqqueue.c ----------------------------------------------------- 如下
#include<stdio.h>
#include "seqqueue.h"
#include <stdlib.h>
#include <string.h>
Queue *CreateQueue()
{
Queue *pQueue = (Queue *)malloc(sizeof(Queue));
if(NULL == pQueue)
{
return NULL;
}
memset(pQueue, 0, sizeof(Queue));
return pQueue;
}
int enQueue(Queue *pQueue, data_t tData)
{
if(NULL == pQueue)
{
return QUEUE_ERR;
}
pQueue->data[pQueue->iRear] = tData;
pQueue->iRear++;
pQueue->count++;
return QUEUE_OK;
}
int deQueue(Queue *pQueue, data_t *pData)
{
if(NULL == pQueue || NULL == pData)
{
return QUEUE_ERR;
}
//先将原来的值保存起来
//再移动队头
*pData = pQueue->data[pQueue->iFront];
pQueue->iFront++;
pQueue->count--;
return QUEUE_OK;
}
int isEmpty(Queue *pQueue)
{
if(NULL == pQueue)
{
return QUEUE_ERR;
}
if(0 == pQueue->count)
{
return QUEUE_EMPTY;
}
return QUEUE_OK;
}
int isFull(Queue *pQueue)
{
if(NULL == pQueue)
{
return QUEUE_ERR;
}
if(SIZE == pQueue->count)
{
return QUEUE_FULL;
}
return QUEUE_OK;
}
void destroyQueue(Queue **ppQueue)
{
if(NULL == ppQueue || NULL == *ppQueue)
{
return;
}
free(*ppQueue);
*ppQueue = NULL;
}
3.main.c ----------------------------------------------------- 如下
#include<stdio.h>
#include "seqqueue.h"
int main()
{
Queue *pQueue = CreateQueue();
data_t data;
while(QUEUE_FULL != isFull(pQueue))
{
scanf("%d", &data);
enQueue(pQueue, data);
}
printf("出队的结果为:");
while(QUEUE_EMPTY != isEmpty(pQueue))
{
deQueue(pQueue, &data);
printf("%d ", data);
}
printf("\n");
destroyQueue(&pQueue);
return 0;
}
三.链式队列的实现
定义结构体:
Struct QueueNode
{
Data_t data;
Struct QueueNode *pNext;
};
Struct Queue
{
Struct QueueNode *pHead;
Struct QueueNode *pTail;
Int count;
};
代码实现:
1.queue.h ----------------------------------------------------- 如下
#ifndef _QUEUE_H_
#define _QUEUE_H_
typedef int data_t;
typedef struct QueueNode
{
data_t data;
struct QueueNode *pNext;
}QueueNode;
typedef struct Queue
{
QueueNode *pHead;
QueueNode *pTail;
int count;
}Queue;
enum QUEUE_OP
{
QUEUE_ERR = -1,
QUEUE_OK,
QUEUE_EMPTY
};
Queue *createQueue();
int enQueue(Queue *pQueue, data_t tData);
int deQueue(Queue *pQueue, data_t *pData);
int isEmpty(Queue *pQueue);
void destroyQueue(Queue **ppQueue);
#endif
2.queue.c ----------------------------------------------------- 如下
#include<stdio.h>
#include "queue.h"
#include <stdlib.h>
#include <string.h>
Queue *createQueue()
{
Queue *pQueue = (Queue *)malloc(sizeof(Queue));
if(NULL == pQueue)
{
return NULL;
}
memset(pQueue, 0, sizeof(Queue));
return pQueue;
}
int enQueue(Queue *pQueue, data_t tData)
{
if(NULL == pQueue)
{
return QUEUE_ERR;
}
QueueNode *pNode = (QueueNode *)malloc(sizeof(QueueNode));
if(NULL == pNode)
{
return QUEUE_ERR;
}
memset(pNode, 0, sizeof(QueueNode));
pNode->data = tData;
//当为空队列时,需要单独处理
if(0 == pQueue->count)
{
pQueue->pHead = pNode;
pQueue->pTail = pNode;
pQueue->count++;
return QUEUE_OK;
}
pQueue->pTail->pNext = pNode;
//更新pTail
pQueue->pTail = pNode;
pQueue->count++;
return QUEUE_OK;
}
int deQueue(Queue *pQueue, data_t *pData)
{
if(NULL == pQueue)
{
return QUEUE_ERR;
}
QueueNode *pDel = pQueue->pHead;
*pData = pDel->data;
pQueue->pHead = pDel->pNext;
free(pDel);
pDel = NULL;
pQueue->count--;
return QUEUE_OK;
}
int isEmpty(Queue *pQueue)
{
if(NULL == pQueue)
{
return QUEUE_ERR;
}
if(0 == pQueue->count)
{
return QUEUE_EMPTY;
}
return QUEUE_OK;
}
void destroyQueue(Queue **ppQueue)
{
if(NULL == ppQueue || NULL == *ppQueue || NULL == (*ppQueue)->pHead)
{
return;
}
QueueNode *pDel = (*ppQueue)->pHead;
while(pDel != NULL)
{
(*ppQueue)->pHead = pDel->pNext;
free(pDel);
pDel = (*ppQueue)->pHead;
}
free(*ppQueue);
*ppQueue = NULL;
}
3.main.c ----------------------------------------------------- 如下
#include<stdio.h>
#include "queue.h"
int main()
{
Queue *pQueue = createQueue();
data_t data;
while(1)
{
printf("请入队:");
scanf("%d", &data);
if(0 == data)
{
break;
}
enQueue(pQueue, data);
}
printf("出队结果为:");
while(QUEUE_EMPTY != isEmpty(pQueue))
{
deQueue(pQueue, &data);
printf("%d ", data);
}
printf("\n");
destroyQueue(&pQueue);
return 0;
}
总结:
1、线性表的特点
逻辑结构是一对一
存储结构有顺序存储和链式存储
2、我们学过了哪些线性表
顺序表 单链表 双向链表 栈 队列
3、栈和队列与顺序表和链表的联系和区别是什么
栈和队列属于顺序表和链表,栈和队列只是在他们的基础上进行了限制
4、顺序表和链表的区别
<1>顺序表是连续存储,链表是不连续的
<2>顺序表插入和删除需要数据搬移,效率低
<3>顺序表的查找效率非常高,只需要知道下标就可以找到
<4>链表的插入和删除效率比顺序表高,不需要数据搬移
<5>链表的查找效率低,需要遍历
一、树–二叉树
1、基本概念
(1)节点的度数:一个节点的子树的个数
(2)树的度数:一棵树的度数是指该树中节点的最大度数。
(3)叶子节点:度数为0的节点
(4)分支节点:度数不为0的节点
(5)根节点没有前驱节点,叶子节点没有后继节点
2、二叉树
(1)概念:一个节点最多只有两个节点,而且是严格区分左右的,哪怕只有只有一个子节点,也要区分左右,所以二叉树是有序树
(2)二叉树的性质
<1>二叉树第i(i≥1)层上的节点最多为2^(i-1)个。
<2>深度为k(k≥1)的二叉树最多有2^k-1个节点。
<3>在任意一棵二叉树中,树叶的数目比度数为2的节点的数目多一。
n0:度数为0的节点的个数
N1:度数为1的节点的个数
N2:度数为2的节点的个数
总节点数为各类节点之和:n = n0 + n1 + n2
总节点数为所有子节点数加一:n = n1 + 2*n2 + 1
故得:n0 = n2 + 1 ;
<4>满二叉树 :深度为k(k≥1)时有2^k-1个节点的二叉树。
<5>完全二叉树 :只有最下面两层有度数小于2的节点,且最下面一层的叶节点集中在最左边的若干位置上。
具有n个节点的完全二叉树的深度为
(log2n)+1或『log2(n+1)˥。
》k-1 <= log2n < k =>k <= log2n+1 < k+1=> log2n < k <= log2n+1 k是整数===》k = log2n+1
3、二叉树的存储
二叉树逻辑结构:一对多
存储结构:顺序存储和链式存储
链式存储中节点的描述方法:
Struct TreeNode
{
Data_t data;
Struct TreeNode *lChild;
Struct TreeNode *rChild;
};
4、二叉树的遍历
二叉树的遍历是指按某条搜索路径访问树中每个结点,使得每个结点均被访问一次,而且仅被访问一次。由于二叉树是一种非线性结构,每个结点都可能有两棵子树,因而需要寻找一种规律,以便使二叉树.上的结点能排列在一一个线性队列上,进而便于遍历。
由二叉树的递归定义可知,遍历一棵二叉树便要决定对根结点N、左子树L和右子树R的访问顺序。按照先遍历左子树再遍历有子树的原则,常见的遍历次序有先序(NLR)、 中序(LNR)和后序(LRN)三种遍历算法,其中“序”指的是根结点在何时被访问。
<递归遍历:>
(1)先根遍历(先序遍历):先访问树根,再访问左子树,最后访问右子树
void PreOrder (TreeNode *pRoot)
{
if (NULL == pRoot)
{
visit (pRoot) ; //访间根结点
// printf("%c ", pRoot->data);
PreOrder (pRoot->lchild) ;//递归遍历左子树
PreOrder (pRoot->rchild) ;//递归遍历右子树
}
}
中根遍历(中序遍历):先访问左子树,再访问树根,最后访问右子树
vold InOrder(TreeNode *pRoot)
{
if (NULL == pRoot)
{
InOrder (pRoot->lchild); //递归遍历左子树
visit(pRoot) ; //访问根结点
// printf("%c ", pRoot->data);
InOrder (pRoot->rchild) ;//递归遍历右子树
}
}
后根遍历(后序遍历):先访问左子树,再访问右子树,最后访问树根
void PostOrder (TreeNode *pRoot)
{
If(NULL == pRoot)
{
Postorder (pRoot->lchild); //递归遍历左子树
Postorder (pRoot->rchild); //递归遍历右子树
visit(pRoot);//访问根结点
// printf("%c ", pRoot->data);
}
}
<层次遍历:>
二叉树的层次遍历
如图所示为二叉树的层次遍历,即按照箭头所指方向,按照1,2, 3,4的层次顺序,对二叉树中的各个结点进行访问。
要进行层次遍历,需要借助一个队列。先将二叉树根结点入队,然
后出队,访问出队结点,若它有左子树,则将左子树根结点入队:若它有右子树,则将右子树根结点入队。然后出队,访问出队结果…如此反复,直至队列为空。
二叉树的层次遍历算法如下:
void Levelorder (BiTree T)
{
InitQueue(Q) ;//初始化辅助队列
BiTree Pi
EnQueue(Q,T) ;//将根结点入队
while ( IsEmpty(Q)) //队列不空则循环
{
DeQueue(O,p)//队头结点出队
visit(p) ;//访问出队结点
if (p->1child! =NULL)
EnQueue (Q,p->lch11d); //左子树不空, 则左子树根结点入队
if (p->rchild!=NULL)
EnQueue (Q,p->rchild); //右子树不空, 则右子树根结点入队
}
}
|
|
|
|
二.代码实现
1.tree.h----------------------------------------------------- 如下
#ifndef _TREE_H_
#define _TREE_H_
typedef char data_tree;
typedef struct TreeNode
{
data_tree data;
struct TreeNode *lChild, *rChild;
}TreeNode;
void createTree(TreeNode **ppRoot);
void preOrder(TreeNode *pRoot);
void inOrder(TreeNode *pRoot);
void postOrder(TreeNode *pRoot);
void destroyTree(TreeNode **ppRoot);
void levelOrder(TreeNode *pRoot);
#endif
2.tree.c----------------------------------------------------- 如下
#include<stdio.h>
#include "tree.h"
#include <stdlib.h>
#include <string.h>
#include "queue.h"
void createTree(TreeNode **ppRoot)
{
data_tree data;
printf("input:");
scanf("%c", &data);
getchar();
if('#' == data)
{
//此时没有左子树或者右子树
*ppRoot = NULL;
return;
}
else
{
//先创建节点
*ppRoot = (TreeNode *)malloc(sizeof(TreeNode));
if(NULL == *ppRoot)
{
return;
}
(*ppRoot)->data = data;
createTree(&((*ppRoot)->lChild));
createTree(&((*ppRoot)->rChild));
}
}
void preOrder(TreeNode *pRoot)
{
if(NULL == pRoot)
{
return;
}
printf("%c ", pRoot->data);
preOrder(pRoot->lChild);
preOrder(pRoot->rChild);
}
void inOrder(TreeNode *pRoot)
{
if(NULL == pRoot)
{
return;
}
inOrder(pRoot->lChild);
printf("%c ", pRoot->data);
inOrder(pRoot->rChild);
}
void postOrder(TreeNode *pRoot)
{
if(NULL == pRoot)
{
return;
}
postOrder(pRoot->lChild);
postOrder(pRoot->rChild);
printf("%c ", pRoot->data);
}
void destroyTree(TreeNode **ppRoot)
{
if(NULL == ppRoot || NULL == *ppRoot)
{
return;
}
destroyTree(&((*ppRoot)->lChild));
destroyTree(&((*ppRoot)->rChild));
free(*ppRoot);
*ppRoot = NULL;
}
void levelOrder(TreeNode *pRoot)
{
if(NULL == pRoot)
{
return;
}
//创建队列
Queue *pQueue = createQueue();
//根节点入队
enQueue(pQueue, pRoot);
//只要队列不为空,就出队
//并且判断出队的节点有无左右子树
//如果有就入队
while(QUEUE_EMPTY != isEmpty(pQueue))
{
TreeNode *pNode;
deQueue(pQueue, &pNode);
printf("%c ", pNode->data);
if(pNode->lChild != NULL)
{
enQueue(pQueue, pNode->lChild);
}
if(pNode->rChild != NULL)
{
enQueue(pQueue, pNode->rChild);
}
}
printf("\n");
}
3.main.c----------------------------------------------------- 如下
#include<stdio.h>
#include "tree.h"
int main()
{
TreeNode *pRoot = NULL;
createTree(&pRoot);
levelOrder(pRoot);
destroyTree(&pRoot);
return 0;
}