C语言数据结构

实验

实验二

#include<iostream>
#include"string"
#include<queue>using  namespace  std;template<typename  E>
class  BinNode//结点类
{private:BinNode* lc;//左孩子BinNode* rc;//右孩子E  elem;
public:BinNode()//默认构造函数,设置左右孩子为空{lc = rc = NULL;}BinNode(E  tmp, BinNode* l = NULL, BinNode* r = NULL)//带参构造函数{elem = tmp;lc = l;rc = r;}BinNode* left()//返回左孩子{return lc;}BinNode* right()//返回右孩子{return rc;}void  setLeft(BinNode* l)//设置左孩子{lc = l;}void  setRight(BinNode* r)//设置右孩子{rc = r;}void  setValue(E  tmp)//设置当前结点的值{elem = tmp;}E  getValue()//获得当前结点的值{return elem;}bool  isLeaf()//判断当前结点是否为叶子结点{return (lc == NULL) && (rc == NULL);}
};template<typename  E>
class  BinTree//二叉树类
{private:BinNode<E>* root;//根结点void  clear(BinNode<E>* r)//清空二叉树{if (r == NULL) return;clear(r->left());clear(r->right());delete r;}void  preOrder(BinNode<E>* tmp, void(*visit)(BinNode<E>* node))//先序遍历,void(*visit)(BinNode<E>*node)为一个函数指针参数,用visit代替传进来的函数,在遍历函数中使用传进来的函数功能{if (tmp != NULL) {visit(tmp);preOrder(tmp->left(), visit);preOrder(tmp->right(), visit);}}void  inOrder(BinNode<E>* tmp, void(*visit)(BinNode<E>* node))//中序遍历,void(*visit)(BinNode<E>*node)为一个函数指针参数,用visit代替传进来的函数,在遍历函数中使用传进来的函数功能{if (tmp != NULL) {inOrder(tmp->left(), visit);visit(tmp);inOrder(tmp->right(), visit);}}void  postOrder(BinNode<E>* tmp, void(*visit)(BinNode<E>* node))//后序遍历,void(*visit)(BinNode<E>*node)为一个函数指针参数,用visit代替传进来的函数,在遍历函数中使用传进来的函数功能{if (tmp != NULL) {postOrder(tmp->left(), visit);postOrder(tmp->right(), visit);visit(tmp);}}void  LevelOrderTranverse(BinNode<E>* tmp, void(*visit)(BinNode<E>* node))//层次遍历,void(*visit)(BinNode<E>*node)为一个函数指针参数,用visit代替传进来的函数,在遍历函数中使用传进来的函数功能{queue<BinNode<E>*> q;if (tmp != NULL) { q.push(tmp); }//压入队尾BinNode<E>* b;while (!q.empty()) {b = q.front();//b等于队头元素visit(b);q.pop();//弹出队头元素if (b->left()) {q.push(b->left());//压入b的左孩子}if (b->right()) {q.push(b->right());//压入b的右孩子}}}int  BinTreeDepth(BinNode<E>* tmp)//获得二叉树的深度{if (BinTreeHeight(tmp) > 0) return BinTreeHeight(tmp) - 1;else return 0;}int  BinTreeNodes(BinNode<E>* tmp)//获得二叉树的结点数{if (tmp != NULL){return (BinTreeNodes(tmp->left()) + BinTreeNodes(tmp->right()) + 1);}else return 0;}int  BinTreeHeight(BinNode<E>* tmp)//获得二叉树的高度{if (tmp == NULL){return 0;}if (tmp->isLeaf()){return 1;}int lh = BinTreeHeight(tmp->left());int rh = BinTreeHeight(tmp->right());return 1 + (lh > rh ? lh : rh);}int  BinTreeLeafs(BinNode<E>* tmp)//获得二叉树的叶子结点数{if (tmp == NULL) return 0;if (tmp->isLeaf()) return 1;return BinTreeLeafs(tmp->left()) + BinTreeLeafs(tmp->right());}bool  find(BinNode<E>* tmp, E  e)//查找二叉树中是否含有某个名为e的结点{if (tmp == NULL) return false;if (tmp->getValue() == e) return true;bool lresult = find(tmp->left(), e);bool rresult = find(tmp->right(), e);return lresult || rresult;}
public:BinTree()//默认构造函数{root = new  BinNode<E>;}~BinTree()//析构函数{clear(root);}bool  BinTreeEmpty()//判断二叉树是否为空{if (root == NULL)return  true;elsereturn  false;}BinNode<E>* getRoot()//获得根节点{return  root;}void  setRoot(BinNode<E>* r)//设置根节点{root = r;}//下面的函数是对外的函数,所以内部还会有一些同名的函数,但是参数列表不一样,实现数据的封装,外部的调用不会涉及到内部的数据对象void  clear()//清空二叉树{clear(root);root = NULL;}void  preOrder(void(*visit)(BinNode<E>* node))//先序遍历,传入相对应的访问函数即可对该当前结点实现不同功能的访问(本程序为输出){preOrder(root, visit);}void  inOrder(void(*visit)(BinNode<E>* node))  //先序遍历,传入相对应的访问函数即可对该当前结点实现不同功能的访问(本程序为输出){inOrder(root, visit);}void  postOrder(void(*visit)(BinNode<E>* node))//先序遍历,传入相对应的访问函数即可对该当前结点实现不同功能的访问(本程序为输出){postOrder(root, visit);}void  LevelOrderTranverse(void(*visit)(BinNode<E>* node))//先序遍历,传入相对应的访问函数即可对该当前结点实现不同功能的访问(本程序为输出){LevelOrderTranverse(root, visit);}int  BinTreeDepth()//获得二叉树深度{return  BinTreeDepth(root);}int  BinTreeNodes()//获得二叉树结点数{return  BinTreeNodes(root);}int  BinTreeHeight()//获得二叉树高度{return  BinTreeHeight(root);}int  BinTreeLeafs()//获得二叉树叶子结点数{return  BinTreeLeafs(root);}bool  find(E  e)//查找二叉树中是否存在名为e的结点{return  find(root, e);}
};template<typename  E>
void  printNode(BinNode<E>* tmp)//打印结点的值的函数
{cout << tmp->getValue() << "  ";
}template<typename  E>
BinNode<E>* creatBinaryTree(string  s[], int& x, int  n)//构建二叉树的主函数,根据先序遍历,采用递归思想构建
{if (s[x] == "/")return  NULL;else{BinNode<E>* node = new  BinNode<E>(s[x]);x = x + 1;if (x < n);node->setLeft(creatBinaryTree<E>(s, x, n));x = x + 1;if (x < n);node->setRight(creatBinaryTree<E>(s, x, n));return  node;}
}void  creatBinaryTree(BinTree<string>* BT)//构建二叉树的函数,包含了上面的构建二叉树的主函数,仅仅起到了在主函数中简洁一些的作用
{//cout  <<  "现在进入构建二叉树程序......"  <<  endl;//cout  <<  "请输入二叉树有多少个结点(空结点也计算其中)"  <<  endl;int  n = 0;cin >> n;//cout  <<  "请按preorder顺序输入,遇到NULL请输入'/',用空格隔开或者回车隔开均可以"  <<  endl;string* s = new  string[n];for (int i = 0; i < n; i++){cin >> s[i];}int  now = 0;BT->setRoot(creatBinaryTree<string>(s, now, n));
}int  main()
{//本程序的二叉树是一个模板类,若想改变为别的类型,可以在相关的地方在“<>”中修改相关参数,本程序默认为最具有普遍性的stringBinTree<string>* BT = new  BinTree<string>;creatBinaryTree(BT);string  strfind;cin >> strfind;//在这里,已经构建好了一棵二叉树//下面是二叉树的基本函数操作的展示cout << "0:判断是否为空树:";if (BT->BinTreeEmpty() == true)cout << "是" << endl;elsecout << "否" << endl;cout << "1:前序遍历:";BT->preOrder(printNode);cout << endl;cout << "2:中序遍历:";BT->inOrder(printNode);cout << endl;cout << "3:后序遍历:";BT->postOrder(printNode);cout << endl;cout << "4:层次遍历:";BT->LevelOrderTranverse(printNode);cout << endl;cout << "5:记录树的深度:";cout << BT->BinTreeDepth() << endl;cout << "6:记录树的高度:";cout << BT->BinTreeHeight() << endl;cout << "7:统计结点:";cout << BT->BinTreeNodes() << endl;cout << "8:统计叶子结点:";cout << BT->BinTreeLeafs() << endl;cout << "9:查找" << strfind << ":";if (BT->find(strfind) == true)cout << "存在" << endl;elsecout << "不存在" << endl;cout << "10:是否清空:";BT->clear();cout << "已清空" << endl;cout << "5:记录树的深度:";cout << BT->BinTreeDepth() << endl;cout << "6:记录树的高度:";cout << BT->BinTreeHeight() << endl;cout << "7:统计结点:";cout << BT->BinTreeNodes() << endl;cout << "8:统计叶子结点:";cout << BT->BinTreeLeafs() << endl;return  0;
}

前言

结构体的使用

malloc()动态分配内存

#include <stdio.h>
#include <malloc.h>
int main ()
{int a[5]={4,10,2,8,6};int len;scanf("%d",&len);int *pArr = (int *)malloc(sizeof(int)*len);for(int i=0; i<len; i++) scanf("%d",&pArr[i]);for(int i=0; i<len; i++) printf("%d\n",*(pArr+i));//*pArr = 4;//类似于a[0]=4;//pArr[1] = 10;//类似于a[1]=10;free(pArr);//把pArr所代表的动态分配的20个字节的内存释放return 0;
}

连续存储数组的算法演示

#include<bits/stdc++.h>
using namespace std;struct Arr
{int* pBase;//存储的是数组第一个元素的地址 int len;//数组所能容纳的最大元素的个数 int cnt;//当前数组有效元素的个数
};void init_arr(struct Arr *pArr,int length);//初始化
bool append_arr(struct Arr *pArr, int val);//尾加
bool insert_arr(struct Arr *pArr, int pos, int val); //插入值   pos的值从1开始
bool delete_arr(struct Arr *pArr, int pos, int* pVal);
bool is_empty(struct Arr* pArr);
bool is_full(struct Arr* pArr);
void sort_arr(struct Arr* pArr);
void show_arr(struct Arr* pArr);//打印数组
void inversion_arr(struct Arr* pArr);//倒置数组 int main()
{struct Arr arr;int val;init_arr(&arr,6);append_arr(&arr,1);show_arr(&arr);delete_arr(&arr,1,&val);append_arr(&arr,2);append_arr(&arr,3);append_arr(&arr,4);append_arr(&arr,5);insert_arr(&arr,7,99);show_arr(&arr);inversion_arr(&arr);show_arr(&arr);sort_arr(&arr);show_arr(&arr);return 0;
} void init_arr(struct Arr *pArr,int length)
{pArr->pBase = (int*)malloc(sizeof(int)*length);if(NULL == pArr->pBase)//如果分配不成功 {cout<<"动态内存分配失败"<<endl;exit(-1);//终止整个程序 }else{pArr->len = length;pArr->cnt = 0;} return;
}bool append_arr(struct Arr *pArr, int val)
{if(is_full(pArr)) return 0;//如果已满则加不进去 返回false else//未满则增加val到末尾 {pArr->pBase[(pArr->cnt)++] = val;return 1;}
}bool insert_arr(struct Arr *pArr, int pos, int val)
{if(is_full(pArr)) return 0;if(pos<1 || pos>pArr->cnt+1) return 0;for(int i=pArr->cnt-1; i>=pos-1; --i) pArr->pBase[i+1] = pArr->pBase[i];pArr->pBase[pos-1] = val;(pArr->cnt)++;return 1;
}bool delete_arr(struct Arr *pArr, int pos, int* pVal)
{if(is_empty(pArr)) return 0;if(pos<1 || pos>pArr->cnt) return 0;*pVal=pArr->pBase[pos-1];//把要删除的值赋给*pVal for(int i=pos; i<pArr->cnt;++i) pArr->pBase[i-1] = pArr->pBase[i];pArr->cnt--;//有效个数减1return 1;
}bool is_empty(struct Arr* pArr)
{if(0 == pArr->cnt) return 1;else return 0;
}bool is_full(struct Arr* pArr)
{if(pArr->cnt == pArr->len) return 1;else return 0;
}void sort_arr(struct Arr* pArr)
{for(int i=0;i<pArr->cnt-1;i++)//冒泡排序 {for(int j=i+1;j<pArr->cnt;j++){if(pArr->pBase[i]>pArr->pBase[j]){int temp = pArr->pBase[i];pArr->pBase[i] = pArr->pBase[j];pArr->pBase[j] = temp;}}}
}void show_arr(struct Arr* pArr)
{if(is_empty(pArr)) cout<<"数组为空!"<<endl;else{for(int i=0;i<pArr->cnt;i++) printf("%d ",pArr->pBase[i]);//先等于 再自增 cout<<endl;}
}void inversion_arr(struct Arr* pArr)
{int i=0;int j=pArr->cnt-1;while(i<j)//互换{int temp = pArr->pBase[i];pArr->pBase[i] = pArr->pBase[j];pArr->pBase[j] = temp;i++; j--;} return;
}

链表

typedef的用法

#include <stdio.h>typedef int INT;//为int再取一个名字INT
typedef struct student
{int sid;char name[100];char sex;
}* PST,ST;//ST为struct student, PST为struct student*int main()
{struct student st; //等价于ST st;struct student* ps = &st;//等价于ST* ps = &st; 等价于PST ps = &st;
}

链表的定义

n个节点离散分配 彼此通过指针相连 首节点没有前驱节点 尾节点没有后续节点

5个专业术语

首节点:第一个有效节点

尾节点:最后一个有效节点

头节点:第一个有效节点之前的那个节点 头节点并不存放有效数据 加头结点的目的主要是为了方便堆链表操作 头节点数据类型和首节点一样

头指针:指向头结点的指针变量(存放头节点地址)

尾指针:指向尾结点的指针变量(存放尾节点地址)

**确定一个链表需要几个参数:**只需要一个参数:头指针

链表分类: 单链表

​ 双链表:每个节点有两个指针域

​ 循环链表:能通过任何一个节点找到其他所有节点

​ 非循环链表

链表的实现

#include<bits/stdc++.h>
using namespace std;typedef struct Node
{int data;//数据域 struct Node* pNext;//指针域
}NODE,*PNODE;//NODE等价于struct Node    PNODE等价于struct Node*PNODE create_list();
void traverse_list(PNODE pHead);//遍历输出
void is_empty(PNODE pHead);
int length_list(PNODE);//求链表长度
bool insert_list(PNODE pHead,int pos,int val);//插入
bool delete_list(PNODE pHead ,int pos,int* val);//删除
void sort_list(PNODE);//排序 int main()
{PNODE pHead = NULL;//等价于struct Node* pHead = NULL;pHead = create_list(); //create_list()功能为创建一个非循环单链表,并将改链表头结点的地址赋给pHead traverse_list(pHead);is_empty(pHead);cout<<"链表长度为:"<<length_list(pHead)<<endl;void sort_list(PNODE pHead);insert_list(pHead,3,33);sort_list(pHead);traverse_list(pHead);return 0;
} PNODE create_list()
{int len;//用来存放有效节点的个数int val;//用来存放用户输入的结点的值 //分配了一个不存放有效数据的头节点PNODE pHead = (PNODE)malloc(sizeof(NODE)); if(NULL==pHead){cout<<"分配失败,程序终止!"<<endl;exit(-1); }//初始化pTail 永远指向最后一个节点 PNODE pTail = pHead;pTail->pNext = NULL;cout<<"请输入您需要生成的链表节点的个数:len=";cin>>len;for(int i=0;i<len;i++){cout<<"请输入第"<<i+1<<"个节点的值:"; cin>>val; PNODE pNew = (PNODE)malloc(sizeof(NODE));if(NULL==pNew){cout<<"分配失败,程序终止!"<<endl;exit(-1); }pNew->data = val;//数据域赋值//指针域赋值pTail->pNext = pNew;pNew->pNext = NULL;pTail = pNew; } return pHead;
}void traverse_list(PNODE pHead)
{PNODE p = pHead->pNext;while(NULL != p){cout<<p->data<<" ";p = p->pNext;}cout<<endl;return;
}void is_empty(PNODE pHead)
{if(pHead->pNext == NULL) {cout<<"链表为空!"<<endl; }else {cout<<"链表不为空!"<<endl;}return;
} int length_list(PNODE pHead)
{PNODE p = pHead->pNext;int len = 0;while(NULL != p) {++len;p = p->pNext;}return len;
}//非常难  要多看
bool insert_list(PNODE pHead,int pos,int val)
{int i=0;PNODE p = pHead;while(NULL!=p && i<pos-1){p = p->pNext;++i;}if(i>pos-1 || NULL==p) return 0;PNODE pNew = (PNODE)malloc(sizeof(NODE));if(NULL==pNew){cout<<"动态内存分配失败!"<<endl;exit(-1);}pNew->data = val;PNODE q = p->pNext;p->pNext = pNew;pNew->pNext = q;return 1;
}//非常难  要多看
bool delete_list(PNODE pHead ,int pos,int* val)
{int i=0;PNODE p = pHead;while(NULL!=p->pNext && i<pos-1){p = p->pNext;++i;}if(i>pos-1 || NULL==p->pNext) return 0;PNODE q = p->pNext;*val = q->data;//删除p节点后面的节点 p->pNext = p->pNext->pNext;free(q);q = NULL;return 1;
}void sort_list(PNODE pHead)
{PNODE p,q;for(p=pHead->pNext;p->pNext!=NULL;p=p->pNext){for(q=p->pNext;q!=NULL;q=q->pNext){if(p->data > q->data){int t=p->data;p->data=q->data;q->data=t;}}}return;
}

简要介绍

定义:一种可以实现”先进后出“的存储结构

分类:静态栈 动态栈

栈的实现

#include<bits/stdc++.h>
using namespace std;typedef struct Node
{int data;//数据域 struct Node* pNext;//指针域
}NODE,*PNODE;//NODE等价于struct Node    PNODE等价于struct Node*typedef struct Stack
{PNODE pTop;//不停变化 PNODE pBottom;//一般不变
}STACK,*PSTACK;void init(PSTACK);//栈初始化
void push(PSTACK,int);//入栈
void traverse(PSTACK);//遍历输出
void pop(PSTACK,int*);//出栈
void clear(PSTACK pS);//清空 int main()
{int val;//保存出战元素的值 STACK S;//STACK等价于struct Stack init(&S);push(&S,1);push(&S,2);push(&S,3);push(&S,4);push(&S,5);push(&S,6);traverse(&S);pop(&S,&val);traverse(&S);clear(&S);traverse(&S);return 0;
} void init(PSTACK pS)
{pS->pTop = (PNODE)malloc(sizeof(NODE));if(NULL==pS->pTop){cout<<"动态内存分配失败!"<<endl;exit(-1);} else{pS->pBottom = pS->pTop;pS->pTop->pNext = NULL;//头节点指针域置为空 }
}void push(PSTACK pS,int val)
{PNODE pNew = (PNODE)malloc(sizeof(NODE));pNew->data = val;pNew->pNext = pS->pTop;//不能改成pS->pBottompS->pTop = pNew;return;
}void traverse(PSTACK pS)
{PNODE p = pS->pTop;while(p!=pS->pBottom){cout<<p->data<<" ";p = p->pNext;}cout<<endl;return;
}bool empty(PSTACK pS)
{if(pS->pBottom == pS->pTop) return 1;else return 0;
}//把pS所指向的栈出栈一次  并把出栈元素存入val形参所指向的变量中  如果出栈失败则返回false 否则返回true
void pop(PSTACK pS,int* pval)
{if(empty(pS)){cout<<"出栈失败!"<<endl;} else{PNODE r = pS->pTop;*pval = r->data;pS->pTop = pS->pTop->pNext;free(r);r=NULL;cout<<"出栈成功,出栈的元素是:"<<*pval<<endl;}return;
}void clear(PSTACK pS)//把有效数据全部删除
{if(empty(pS)) return;else{PNODE p = pS->pTop;PNODE q = NULL;while(p != pS->pBottom){q=p->pNext;free(p);//free(p)释放的是p所指的对象 不是p p = q;}pS->pTop = pS->pBottom;return; }
}

队列

简要介绍

定义:一种可以实现“先进先出”的存储结构

分类:链式队列——用链表实现 静态队列——用数组实现(通常都是循环队列)

循环队列需要几个参数来确定: front rear

​ 1.队列初始化:front和rear的值都是0

​ 2.队列非空:front代表队列最后一个元素 rear代表队列最后一个有效元素的下一个元素

​ 3.队列空:front和rear的值相等 但不一定是零

伪算法演示

入队:将值存入r所代表的位置 r=(r+1)%数组的长度

出队:f=(f+1)%数组的长度

如何判断队列是否已满:

​ 1.多增加一个标识参数

​ 2.少用一个元素 如果r和f的值紧挨着 则队列已满

if ((r+1)%数组长度 == f) 已满;
else 不满;

队列的实现

//该程序可存放的最大整型数数目为5(6-1)
#include<bits/stdc++.h>
using namespace std;typedef struct Queue
{int* pBase;int front;int rear;
}QUEUE;void init(QUEUE*);//队列初始化
bool en(QUEUE* ,int val);//入队
bool out(QUEUE* ,int*);//出队
void traverse(QUEUE*);//遍历
bool full(QUEUE*);//判断是否已满
bool empty(QUEUE*);//判断是否为空 int main()
{QUEUE Q;int val;init(&Q);en(&Q,1);en(&Q,2);en(&Q,3);en(&Q,4);en(&Q,5);en(&Q,6);en(&Q,7);en(&Q,8);traverse(&Q);if(out(&Q,&val)){cout<<"出队成功!队列出队的元素是:"<<val<<endl;}else cout<<"出队失败!"<<endl;traverse(&Q);    return 0;
} void init(QUEUE* pQ)
{pQ->pBase = (int*)malloc(sizeof(int)*6);pQ->front = 0;pQ->rear = 0;return;
}bool en(QUEUE* pQ,int val)
{if(full(pQ)) return 0;else{pQ->pBase[pQ->rear] = val;pQ->rear = (pQ->rear+1)%6;return 1;}
}bool out(QUEUE* pQ,int* pVal)
{if(empty(pQ)) return 0;else{*pVal = pQ->pBase[pQ->front];pQ->front = (pQ->front+1)%6;return 1;}
}void traverse(QUEUE* pQ)
{int i=pQ->front;while(i!=pQ->rear){cout<<pQ->pBase[i]<<" ";i = (i+1)%6;}cout<<endl;return;
}bool full(QUEUE* pQ)
{if((pQ->rear+1)%6 == pQ->front) return 1;else return 0;
}bool empty(QUEUE* pQ)
{if(pQ->front == pQ->rear) return 1;else return 0;
}

递归

简要介绍

定义:一个函数自己直接或间接调用自己

举例

//1.求阶乘
#include<bits/stdc++.h>//for循环实现
using namespace std;
int main()
{int val,res=1; cin>>val;for(int i=1;i<=val;i++) res*=i;cout<<res<<endl;return 0;
} #include<bits/stdc++.h>//递归实现
using namespace std;
int f(int n)
{if(n==1) return 1;else return f(n-1)*n;
}int main()
{   int val;cin>>val;cout<<f(val)<<endl;return 0;
} //1+2+...+100
#include<bits/stdc++.h>
using namespace std;
int sum(int n)
{if(1==n) return 1;else return n+sum(n-1);
}
int main()
{cout<<sum(100)<<endl;return 0;
} //汉诺塔
#include<bits/stdc++.h>
using namespace std;
void hannuota(int n,char A,char B,char C)//有n个盘子  从A借助B移到C
{/*  如果是1个盘子直接将A柱子上的盘子借助C移到B否则先将A柱子上的n-1个盘子借助C移到B直接将A柱子上剩余的一个盘子从A移到C最后将B柱子上的n-1个盘子借助A移到C
*/ if(n==1) printf("将编号为%d的盘子直接从%c柱子移到%c柱子\n",n,A,C);else{hannuota(n-1,A,C,B);printf("将编号为%d的盘子直接从%c柱子移到%c柱子\n",n,A,C);hannuota(n-1,B,A,C);}
}
int main()
{int n; cin>>n;hannuota(n,'A','B','C');return 0;
} 

简要介绍

深度:从根节点到最底层节点的层数 根节点是第一层

叶子节点:没有子节点的节点

非终端节点:即叶子节点

度:子节点的个数

数分类

​ 一般数

​ 二叉树:任意一个节点的子节点个数最多两个,且子节点的位置不可更改

​ 一般二叉树

​ 满二叉树:在不增加树的层数的情况下,无法再多添加一个界定的二叉树称为满二叉树

​ 完全二叉树:如果只是删除了满二叉树最底层最右边的连续若干个节点 这样形成的二叉树就是完全二叉树

​ 森林:n个互不相交的数的集合

树的存储

二叉树的存储

连续存储[完全二叉树]

​ 优点:查找某个节点的父节点和字节点速度很快

​ 缺点:耗用内存空间过大

​ 链式存储

​ 一般树的存储

​ 双亲表示法:求父节点方便

​ 孩子表示法:求子节点方便

​ 双亲孩子表示法

​ 二叉树表示法:把一个普通树转化成二叉树来存储 (一定没有右子树)

​ 具体转换方法:设法保证任意一个节点的做指针指向它的第一个孩子 右指针指向它的下一个兄弟 只要满足此条件 就可以把一个普通树转化成二叉树来存储

​ 森林的存储:先把森林转化为二叉树,再存储二叉树

二叉树操作

遍历

先序遍历 [先访问根节点]:先访问根节点 再先序访问左子树 再先序访问右子树(递归)

中序遍历 [中间访问根节点]:中序遍历左子树 再访问根节点 再中序遍历右子树

后序遍历 [最后访问根节点]:后序遍历左子树 再后序遍历右子树 再访问根节点

已知两种遍历序列求原始二叉树

通过先序和中序 或者 中序和后序可以还原出原始二叉树 但是通过先序和后序是无法还原出原始二叉树的**(必须有中序)**

已知先序和中序求后序
已知中序和后序求先序

链式二叉树遍历具体程序演示

#include<bits/stdc++.h>
using namespace std;struct BTNode
{char data;//数据域 struct BTNode* pLchild;//p是指针 L是左 child是孩子struct BTNode* pRchild;//p是指针 R是右 child是孩子
};struct BTNode* CreateBTree();
void PreTraverseBTree(struct BTNode*);
void InTraverseBTree(struct BTNode*);
void PostTraverseBTree(struct BTNode*); int main()
{struct BTNode* pT = CreateBTree(); PreTraverseBTree(pT);//先序遍历输出 InTraverseBTree(pT); //中序遍历输出PostTraverseBTree(pT);//后序遍历输出 return 0;
} struct BTNode* CreateBTree(void)//静态构造树
{struct BTNode* pA = (struct BTNode*)malloc(sizeof(struct BTNode));struct BTNode* pB = (struct BTNode*)malloc(sizeof(struct BTNode));struct BTNode* pC = (struct BTNode*)malloc(sizeof(struct BTNode));struct BTNode* pD = (struct BTNode*)malloc(sizeof(struct BTNode));struct BTNode* pE = (struct BTNode*)malloc(sizeof(struct BTNode));pA->data = 'A';pB->data = 'B';pC->data = 'C';pD->data = 'D';pE->data = 'E';pA->pLchild = pB;pA->pRchild = pC;pB->pLchild = pB->pRchild = NULL;pC->pLchild = pD;pC->pRchild = NULL;pD->pLchild = NULL;pD->pRchild = pE;pE->pLchild = pE->pRchild = NULL;return pA;
}void PreTraverseBTree(struct BTNode* pT)
{if(NULL != pT){cout<<pT->data<<endl;if(NULL != pT->pLchild) PreTraverseBTree(pT->pLchild);if(NULL != pT->pRchild) PreTraverseBTree(pT->pRchild);}
}void InTraverseBTree(struct BTNode* pT)
{if(NULL != pT){if(NULL != pT->pLchild) InTraverseBTree(pT->pLchild);cout<<pT->data<<endl;if(NULL != pT->pRchild) InTraverseBTree(pT->pRchild);}
}void PostTraverseBTree(struct BTNode* pT)
{if(NULL != pT){if(NULL != pT->pLchild) PostTraverseBTree(pT->pLchild);if(NULL != pT->pRchild) PostTraverseBTree(pT->pRchild);cout<<pT->data<<endl;}
}

查找和排序

快速排序法

#include<bits/stdc++.h>
using namespace std;void  QuickSort(int *a,int low,int high);
int FindPos(int *a,int low,int high);int main()
{int a[6] = {2,1,0,5,4,3};QuickSort(a,0,5);//第二个参数表示第一个元素下标   第三个参数表示最后一个元素下标for(int i=0;i<6;i++) cout<<a[i]<<" ";//遍历输出 cout<<endl; return 0;
} void  QuickSort(int *a,int low,int high)
{int pos;if(low < high){pos=FindPos(a,low,high);QuickSort(a,low,pos-1);QuickSort(a,pos+1,high);}
}int FindPos(int *a,int low,int high)
{int val=a[low];while(low<high){while(low<high && a[high]>=val) --high;a[low]=a[high];while(low<high && a[low]<=val) ++low;a[high]=a[low];}//while循环终止后high和low一定是相等的 a[low]=val;return high;
}

HNU数据结构与算法szh相关推荐

  1. Python3-Cookbook总结 - 第一章:数据结构和算法

    第一章:数据结构和算法 Python 提供了大量的内置数据结构,包括列表,集合以及字典.大多数情况下使用这些数据结构是很简单的. 但是,我们也会经常碰到到诸如查询,排序和过滤等等这些普遍存在的问题. ...

  2. 推荐一个关于.NET平台数据结构和算法的好项目

    http://www.codeplex.com/NGenerics 这是一个类库,它提供了标准的.NET框架没有实现的通用的数据结构和算法.值得大家研究. 转载于:https://www.cnblog ...

  3. 数据结构和算法:(3)3.1线性表的顺序存储结构

    -----------------------1.线性表基础操作------------------------ 线性表:(List)由零个或多个数据元素组成的有限序列. 首先他是一个序列,元素之间是 ...

  4. weiss数据结构和算法书的使用说明

    <数据结构与算法分析 C语言描述>Mark Allen Weiss著,冯舜玺译,机械工业出版社.Weiss教授的经典教材三部曲之一,其中的C语言描述版本,也就是本书,被称为20世纪最重要的 ...

  5. 数据结构和算法 -- 学习导图

    数据结构和算法 是作为程序员写出高效代码的基础,为了今后的两年在高效代码之路上持续精进,将按照此学习导图进行 算法和数据结构的刻意练习,同时也希望为同样有高效代码追求的伙伴们提供一条学习路径,共同进步 ...

  6. Java数据结构与算法(第四章栈和队列)

    2019独角兽企业重金招聘Python工程师标准>>> 本章涉及的三种数据存储类型:栈.队列和优先级队列. 不同类型的结构 程序员的工具 数组是已经介绍过的数据存储结构,和其他结构( ...

  7. python数据结构与算法总结

    python常用的数据结构与算法就分享到此处,本月涉及数据结构与算法的内容有如下文章: <数据结构和算法对python意味着什么?> <顺序表数据结构在python中的应用> ...

  8. 学习JavaScript数据结构与算法(一):栈与队列

    本系列的第一篇文章: 学习JavaScript数据结构与算法(一),栈与队列 第二篇文章:学习JavaScript数据结构与算法(二):链表 第三篇文章:学习JavaScript数据结构与算法(三): ...

  9. MySQL索引背后的数据结构及算法原理【转】

    http://blog.codinglabs.org/articles/theory-of-mysql-index.html MySQL索引背后的数据结构及算法原理[转] 摘要 本文以MySQL数据库 ...

最新文章

  1. (二期)IOS调试技巧
  2. 内存条ar开头的如何看大小_软网推荐:明明白白看内存
  3. c语言随机迷宫生成方法,[原创]递归随机迷宫生成算法详解
  4. 7种JIRA集成可优化Java开发流程
  5. mysql不区分大小写设置_mysql设置不区分大小写
  6. 【大事化小,小事化无】的意思和解释
  7. android 多线程编程
  8. ubuntu ffmpeg 批量修改视频分辨率
  9. musictools(无损付费音乐免费下载神器) 最新版 v3.7.0
  10. Vue基础1-如何创建一个vue实例
  11. 苹果7信号天线内部位置_苹果手机的天线在什么位置
  12. 代码里颜色设置表RGB+CMYK
  13. 2022年度总结|我的CSDN成长历程
  14. 京东云主机使用-搭建简单网页(macOS)
  15. python文本关键词提取_python实现关键词提取
  16. 访问学者办理签证的问题整理!
  17. pandas 如何创建空的DataFrame
  18. 第二届先导杯-在曙光超算平台编译cp2k(二)
  19. 银行快消零售行业遏制数据泄露四驾马车
  20. .net软件工程师面试

热门文章

  1. 免费用微软软件,中国学生享用DreamSpark完全攻略
  2. fastboot命令
  3. 完美解决eNSP virtualBox安装完成后只有VirtualBox Host-Only Network #2,Ensp利用虚拟网卡的设备无法启动。eNSP设备AC;AP设备报41错误解决办法。
  4. 最近总结了数据分析必备的一些网站!
  5. ssm+JSP计算机毕业设计游戏网站设计n8q96【源码、程序、数据库、部署】
  6. 基于Java毕业设计音乐管理系统源码+系统+mysql+lw文档+部署软件
  7. 【SpringBoot框架篇】11.Spring Data Jpa实战
  8. java基础面试资料收集篇一
  9. 请收藏:流固耦合经验总结(一)
  10. 未来的工作都被计算机代替,未来计算机或机器人会替代人类的工作吗?为什么?_科技数码通...