基础数据结构算法实现总结,包括链表:顺序存储及链式存储形式下的单链表,双向链表及循环链表的操作实现
队列:循环队列,简单队列
栈:栈的增删改查操作等
字符串数组:KMP算法及BF算法
图:图在邻接表和邻接矩阵存储形式下的BFS和DFS算法实现,迪杰斯特拉算法等经典算法
简单查找与排序算法实现:快速排序等
注:本人才疏学浅,理解有限,所有分享仅供参考;
数据结构与算法教学视频推荐(青岛大学王卓老师)https://www.bilibili.com/video/BV1nJ411V7bd
顺序表中去除重复元素:
在长度为n(n<1000)的顺序表中可能存在着一些值相同的“多余”数据元素(类型为整型),编写一个程序将“多余”的数据元素从顺序表中删除,使该表由一个“非纯表”(值相同的元素在表中可能有多个)变成一个“纯表”(值相同的元素在表中只能有一个)。
第一行输入表的长度n;
第二行输入顺序表初始存放的元素;
第一行输出删除后的元素个数
第二行输出删除后剩余的元素
代码如下:
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int m = 1000;
int n;
struct Data
{
int num;
int flag = 0;
};
typedef struct Sqlist //顺序表结构
{
Data data[m];
int n;
}Sqlist;
void Manage(Sqlist &L) //标记数据中的重复数字
{
for(int i = 0 ; i < n-1;i++){
for(int j = i+1;j < n;j++){
if(L.data[i].num == L.data[j].num) {L.data[j].flag = 1;}
}
}
int num = 0,flag1 = 0;
for(int i = 0;i < n;i++){
if(L.data[i].flag == 0) num++;
}
cout<<num<<endl;
for(int i = 0;i < n;i++){
if(L.data[i].flag == 0 && flag1 == 0) {
cout<<L.data[i].num;
flag1 = 1;
}
else if(L.data[i].flag == 0 && flag1 == 1) cout<<" "<<L.data[i].num;
}
cout<<endl;
}
int main()
{
while(cin>>n){
Sqlist L;
for(int i = 0; i < n;i++){
cin>>L.data[i].num;
}
Manage(L);
}
return 0;
}链表中删除指定元素:
输入n个整数,先按照数据输入的顺序建立一个带头结点的单链表,再输入一个数据m,
将单链表中的值为m的结点全部删除。分别输出建立的初始单链表和完成删除后的单链表。
Input
第一行输入数据个数n;
第二行依次输入n个整数;
第三行输入欲删除数据m。
代码如下:
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
const int N = 1000;
int n,m; //m为要删除的数据值
typedef struct Lnode
{
int num;
struct Lnode *next;
}Lnode,*Lklist;
void InputLklist(Lklist &L)//尾插法创建链表
{
L = new Lnode(); //创建头结点,L指针指向头结点
L -> next = NULL;
Lklist s = L;
for(int i = 0; i < n; i++){
Lklist p = new Lnode();//创建新结点
cin >> p->num;
p -> next = NULL;
s -> next = p;
s = p;//指针指向下一节点
}
}
void ManageLklist(Lklist &L , int &m)
{
Lklist s = L -> next;//s指向要比较的元素
Lklist p = L;//p指向前一个元素,控制删除
int newn = n;//newn记录节点数的变化
for(int i = 0; i < n; i++){
if(s->num == m){
newn--;
p->next = s->next;
s = p->next;
}
else{
p = p->next;
s = s->next;
}
}
n = newn;
}
void OutputLklist(Lklist &L)
{
Lklist p = L->next;
int flag =0;
cout<<n<<endl;
while(p){
if(flag == 0) {
cout<< p->num;
flag = 1;
p = p->next;
}
else{
cout<<" "<<p->num;
p = p->next;
}
}
cout<<endl;
}
int main()
{
Lklist L;
while(cin>>n){
L= NULL;//没进行一次测试就要对对头指针初始化
InputLklist(L);
cin>>m; //输入要删除的元素值
OutputLklist(L);//输出初始数据
ManageLklist(L,m);
OutputLklist(L);//输出删除后的数据
}
return 0;
}循环链表:
n个人想玩残酷的死亡游戏,游戏规则如下:
n个人进行编号,分别从1到n,排成一个圈,顺时针从1开始数到m,数到m的人被杀,剩下的人继续游戏,活到最后的一个人是胜利者。
请输出最后一个人的编号。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N = 1000;
int n,m;
typedef struct Lnode
{
int num;
struct Lnode *next;
}Lnode,*Lklist;
void InputLklist(Lklist &L)
{
L = new Lnode();//创建头节点
L->next = NULL;
Lklist s = L;
for(int i = 1; i <=n ; i++){
Lklist p = new Lnode();
p->next = NULL;
p->num = i;
s ->next = p;
s = p;
}
s->next = L->next;//尾节点指针指向头结点后面节点,形成循环链表
}
void ManageLklist(Lklist &L)
{
cin>>m;//输入要数的数
Lklist p = L->next;
for(int i = n;i > 0; i--){
if(i>1){
for(int j = 0;j < m-2;j++){//找到要杀的那个人的前一个节点
p = p->next;
}
p->next = p->next->next;
p = p->next;//执行完一次游戏后轮到下一个人
}
else L->next = p;//好有一个人的时候,头结点指向该节点
}
}
void OutputLklist(Lklist &L)
{
cout << L->next->num << endl;
}
int main()
{
Lklist L;
while(cin>>n){
InputLklist(L);
ManageLklist(L);
OutputLklist(L);
}
return 0;
}字符串括号匹配问题:
给你一串字符,不超过50个字符,可能包括括号、数字、字母、标点符号、空格,你的任务是检查这一串字符中的( ) ,[ ],{ }是否匹配。
如果匹配就输出“yes”,不匹配输出“no”
代码如下:
#include<iostream>
#include<string.h>
using namespace std;
const int N = 100;
int st = 0;
string str;
typedef struct stack
{
char *top;
char *base;
int size;
int flag;//标志位,如果有多余的右括号直接说明不匹配
}Sqstack;//顺序表
void InsitStack(Sqstack &S)//初始化栈
{
S.base = new char[N];//开辟字符串数组
S.top = S.base;
S.size = 0;
S.flag = 0;
}
void PushStack(Sqstack &S , char &ch)//压入元素
{
*S.top = ch;
S.top++;
S.size++;
}
void OutStack(Sqstack &S)//弹出元素
{
if(S.size > 0){
S.top--;
S.size--;
}
}
char GetStack(Sqstack &S)//返回栈顶元素
{
if(S.size > 0){
char ch;
--S.top;
ch = *S.top;
S.top++;
return ch;
}
}
void JudgeStack(Sqstack &S)
{
char chTem;
for(int i = 0;i < st; i++){
if(str[i] == '(' || str[i] == '[' || str[i] == '{'){
PushStack(S,str[i]);
}
else if(str[i] == ')'){
chTem = GetStack(S);
if(chTem == '(' && str[i] == ')') OutStack(S);
else S.flag = 1;//有一次符号不匹配,直接整个字符中不匹配
}
else if(str[i] == ']'){
chTem = GetStack(S);
if(chTem == '[' && str[i] == ']') OutStack(S);
else S.flag = 1;
}
else if(str[i] = '}'){
chTem = GetStack(S);
if(chTem == '{' && str[i] == '}') OutStack(S);
else S.flag = 1;
}
}
}
void PrintfStack(Sqstack &S)
{
if(S.top == S.base && S.flag == 0) cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
int main()
{
while(cin>>str){//能够直接输入空格
st = str.length();//获取字符长度
Sqstack S;
InsitStack(S);//初始化栈
JudgeStack(S);//对栈进行判断
PrintfStack(S);//输出结果
}
return 0;
}栈的出栈顺序判定问题:
给定一个从1开始的连续整数列1、2、3、4......n。
将上述数列按顺序入栈,中途栈顶元素可以出栈。
再给定一个出栈序列,判断此序列是否合法。
例如,将n设为4。即得到数列1、2、3、4。
再给定出栈序列1、3、4、2。 可以看出,此出栈序列合法。 过程如下,
先将数列1、2、3、4中的元素1入栈,再将其出栈。
然后将元素2、3入栈,将元素3出栈。
最后将元素4入栈,再把栈内的仅余元素4、2出栈。
整个过程中,元素按照1、3、4、2的顺序出栈。证明其合法
输入包括多组测试用例。
对于每组测试用例,第一行包含一个整数n<100,代表从1开始的连续整数列长度。
第二行包含一个长度为n的数列,代表出栈序列。出栈序列的各元素在区间[1,n]内且不重复。
代码如下:
#include<iostream>
using namespace std;
const int N =101;
int n = 0;
int sure[N];//保存给定的出栈次序
typedef struct stack
{
int *top;
int *base;
int size;
}Sqstack;
void InsitStack(Sqstack &S)
{
S.base = new int[N];//开辟一个int型数组
S.top = S.base;
S.size = 0;
}
void PushStack(Sqstack &S , int &tem)
{
*S.top = tem;//注意赋值的时候的写法
S.top++;
S.size++;
}
void OutStack(Sqstack &S)
{
if(S.size > 0){
S.top--;
S.size--;
}
}
int GetStack(Sqstack &S)
{
if(S.size > 0){
int tem;
S.top--;
tem = *S.top;
S.top++;
return tem;
}
}
void ManageStack(Sqstack &S)
{
int j = 0;
for(int i = 1;i <= n; i++){
PushStack(S,i);
while((S.size != 0) && (GetStack(S) == sure[j])){//while循环能够在一次for语句下循环多次,只要条件符合(每次压入后都与出栈顺序进行比较)
OutStack(S);
j++;
}
}
}
void PrintfStack(Sqstack &S)
{
if(S.size == 0) cout<<"Yes"<<endl;//栈空时为正确序列
else cout<<"No"<<endl;
}
int main()
{
while(cin>>n){
Sqstack S;
for(int i = 0; i < n;i++) cin>>sure[i];
InsitStack(S);
ManageStack(S);
PrintfStack(S);
}
}给一个十进制数字,输出他的八进制形式
Input
一个十进制数字(int范围内)
再输入一个数字的表示要转换为R进制
Output
输入数字的R进制结果
Sample Input
7 8
8 8
Sample Output
7
10
代码如下:
//十进制数的进制转置
#include<iostream>
#define MAXSIZE 1000
using namespace std;
typedef struct stack
{
int *top;
int *base;
int size;
}Sqstack;
void InsitStack(Sqstack &S)
{
S.base = new int[MAXSIZE];//开辟数组空间
if(!S.base){
//cout<<"开辟空间失败!!!"<<endl;
}
else{//初始化栈的头指针,尾指针和长度
S.top = S.base;
S.size = 0;
}
}
void PushStack(Sqstack &S,int &size)
{
if(S.top - S.base == MAXSIZE){
//cout<<"栈空间已满。"<<endl;
}
else{
*S.top = size;
S.top++;
S.size++;
}
}
void OutStack(Sqstack &S)
{
if(S.size != 0){
S.top--;
cout<<*S.top;
S.size--;
}
}
int main(){
int num,R;
while(cin>>num){
cout<<"请确定要转换为几进制数:";
cin>>R;
Sqstack S;
InsitStack(S);
int tem;
do{
tem = num%R;
PushStack(S,tem);
num = num/R;
}while(num!=0);
while(S.size != 0){
OutStack(S);
}
cout<<endl;
}
}定义一个数字消除游戏的规则,如果相邻两个数的和为0,就把这两个数消除。
比如一个序列为:1, 2, -2, -1。因为2和-2和为0,所以同时删除,删除之后1和-1和为0,又可以删除。所以最后这个序列为空。
又比如一个序列为:1, 2, -1, -2。因为相邻的没有和为0的所以最后的序列为1, 2, -1, -2。
Input
多组测试数据,对于每组测试数据:
第一行是一个整数N,N < 50
第二行是N个有空格分开的实数,绝对值小于20。
Output
如果经过消除,最后这个序列为空,输出"RedHat V5!"
如果不为空输出剩余数字的和。
Sample Input
4
1 2 -2 -1
4
1 2 -1 -2
Sample Output
RedHat V5!
0
代码如下:
#include<iostream>
#include<math.h>
#define MAXSIZE 50
using namespace std;
typedef struct stack
{
int *top;
int *base;
int size;
}Sqstack;
void InsitStack(Sqstack &S)
{
S.base = new int[MAXSIZE]; //开辟一个MAXSIZE大小的数组空间并将首地址赋给base
if(!S.base){
//cout<<"开辟空间失败"<<endl;
}
else{
S.top = S.base;
S.size = 0;
}
}
void PushStack(Sqstack &S,int n)
{
if(S.top-S.base == MAXSIZE){
//cout<<"数组空间已满,无法存储"<<endl;
}
else{
*S.top = n;
S.top++;
S.size++;
}
}
int GetStack(Sqstack &S)
{
if(S.top == S.base){
//cout<<"栈里没有元素"<<endl;
return 0;
}
else{
int e;
--S.top;
e = *S.top;
S.top++;
return e;
}
}
void OutStack(Sqstack &S)
{
if(S.top != S.base){
S.top--;
S.size--;
}
}
void JudgeStack(Sqstack &S,int a[],int &N)
{
PushStack(S,a[0]);
for(int i = 1;i<N;i++){
if(a[i] + GetStack(S) ==0){
OutStack(S);
}
else{
PushStack(S,a[i]);
}
}
}
void PrintStack(Sqstack &S,int &sum)
{
if(S.top == S.base){
cout<<"RedHat V5!"<<endl;
}
else{
cout<<sum<<endl;
}
}
main()
{
int N;
int a[MAXSIZE];
while(cin>>N){
int sum = 0;
for(int i = 0;i<N;i++){
cin>>a[i];
sum = sum + a[i];
}
Sqstack S;
InsitStack(S);
OutStack(S);
JudgeStack(S,a,N);
PrintStack(S,sum);
}
}顺序表:
//单向链表的增删改查
#include<iostream>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Lnode,*Lklist;
void CreateLklist(Lklist &L,int &n)
{
Lklist Tem = L;
Lklist p;
for(int i = 0;i < n;i++){
p = new Lnode();
cin >> p->data;
Tem->next = p;
Tem = p;
}
cout<<"创建完后有"<<n<<"个元素,分别为:"<<endl;
}
void InsertLklist(Lklist &L,int &n,int &ins)
{
if(ins > n+1 || ins<1){
cout<<"插入位置错误!!!"<<endl;
}
else{
n++;
Lklist Tem = L;
Lklist p = new Lnode();
cout<<"请输入要插入元素的数据:"<<endl;
cin>> p->data;
for(int i = 0;i<ins-1;i++){
Tem = Tem->next;
}
p->next = Tem->next;
Tem->next = p;
cout<<"插入后共有"<<n<<"个元素,在第"<<ins<<"个元素之前插入后:"<<endl;
}
}
void DeleteLklist(Lklist &L,int &n,int &dele)
{
if(dele>n || dele<1){
cout<<"删除位置错误!!!"<<endl;
}
else if(0<dele && dele<n){
n--;
Lklist Tem = L;
for(int i = 0;i<dele-1;i++){
Tem = Tem->next;
}
Tem->next = Tem->next->next;
cout<<"删除后共有"<<n<<"个元素,删除之后的元素为:"<<endl;
}
else{
n--;
Lklist p = L;
for(int i = 0;i<n-1;i++){
p = p->next;
}
p->next = NULL;
cout<<"删除后共有"<<n<<"个元素,删除之后的元素为:"<<endl;
}
}
void LocateLklist(Lklist &L,int &n,int &loc)
{
if(loc<1 || loc>n){
cout<<"查找元素位置错误!!!"<<endl;
}
else{
Lklist Tem = L;
for(int i = 0;i<loc;i++){
Tem = Tem->next;
}
cout<<"你要查找的元素是:"<< Tem->data <<endl;
}
}
void PrintfLklist(Lklist &L,int &n)
{
Lklist p = L;
for(int i = 0;i < n;i++){
p = p->next;
cout<<p->data<<" ";
}
cout<<endl;
}
main()
{
int n,ins,loc,dele;
Lklist L;
while(1){
cout<<"请输入此链表里的元素个数:"<<endl;
cin>>n;
L = new Lnode();
CreateLklist(L,n);
PrintfLklist(L,n);
cout<<"请输入你要在第几个元素前插入:"<<endl;
cin>>ins;
InsertLklist(L,n,ins);
if(0<ins && ins<n+1){
PrintfLklist(L,n);
}
cout<<"请输入你要删除第几个元素:"<<endl;
cin>>dele;
DeleteLklist(L,n,dele);
if(0<dele && dele<n+1){
PrintfLklist(L,n);
}
cout<<"请确定你要查找第几个元素:(范围为1~"<<n<<")"<<endl;
cin>>loc;
LocateLklist(L,n,loc);
free(L);
system("pause");
}
}栈和队列:
/*链式队列的入队列和出队列操作
1.插入在对位,删除在队首(有头结点)
2.链队的长度不确定
*/
#include<iostream>
using namespace std;
typedef struct node
{
int data;
struct node *next;
}Qnode,*QuenePtr;//定义具体的队列内的某一个节点
typedef struct
{
QuenePtr front;//链队中指向头结点类型的指针
QuenePtr rear;//链队的尾指针
}LkQuene;//定义一个链队
void InsitLkQuene(LkQuene &Q)
{
Q.front = new Qnode();//定义头结点
Q.rear = Q.front;//初始情况下头指针与尾指针都指向头结点
Q.front->next = NULL;//初始化时头结点的next域为空
}
void InsertLkQuene(LkQuene &Q)//插入在队尾
{
QuenePtr p = new Qnode();//定义一个新节点,并把地址赋给p
if(p){//地址赋值成功再进行插入
cout<<"请输入插入元素的数据:";
cin>>p->data;
p->next = NULL;
Q.rear->next = p;
Q.rear = p;
cout<<"插入成功"<<endl;
cout<<Q.rear->data<<endl;
}
//free(p);//此处不能free(p),p是创建的的节点,如果free掉,会把创建的节点空间一块释放掉,插入的时候不能free操作
}
void DeleteLkQuene(LkQuene &Q)
{
if(Q.front != Q.rear){//删除在队首
QuenePtr p;
p = Q.front->next;//p指向头结点后一个节点
Q.front->next = p->next;//front的next域改为删除节点的下一个节点
if(Q.rear == p){//特殊情况,队列中只有一个头结点和尾节点,在上述步骤进行完之后,rear指向节点被删除
Q.rear = Q.front;//此时就只有一个头节点,则两者地址相同
}
free(p);
cout<<"删除成功"<<endl;
}
else{
cout<<"队列已经为空!!!"<<endl;
}
}
void PrintLkQuene(LkQuene &Q)
{
if(Q.front == Q.rear){
cout<<"队列为空!!!"<<endl;
}
else{
QuenePtr p = Q.front;
cout<<"队列内元素为:";
while(Q.front != Q.rear){
Q.front = Q.front->next;
cout<<Q.front->data<<" ";
}
cout<<endl;
Q.front = p;
}
}
int main()
{
LkQuene Q;
int flag;
InsitLkQuene(Q);
cout<<"输入1为插入操作,输入2为删除操作,输入3为输出元素操作。请输入:";
while(cin>>flag){
if(flag == 1){
InsertLkQuene(Q);
}
else if(flag == 2){
DeleteLkQuene(Q);
}
else if(flag == 3){
PrintLkQuene(Q);
}
cout<<"输入1为插入操作,输入2为删除操作,输入3为输出元素操作。请输入:";
}
system("pause");
}//链式存储形式下出栈和入栈
#include<iostream>
using namespace std;
typedef struct stack
{
int data;
struct stack *next;
}StackNode,*LkStack;
void CreateLkstack(LkStack &top,int &len)
{
cout<<"请输入数据:"<<endl;
for(int i = 0;i<len;i++){
LkStack p = new StackNode();
cin>>p->data;
p->next = top;//用尾插法把新建立的节点的指针域联系起来(此时节点的指针域为上一个节点地址,若该节点是第一个节点,则该节点的指针域为空)
top = p;//赋给top指针当前节点地址,以便作为下一节点的指针域(即修改栈顶指针)
}//n个节点建立之后,top指针指向栈顶位置,链的顺序是自上而下的
cout<<"此时栈内元素个数为:"<<len<<endl;
}
void PopStack(LkStack &top,int &out,int &len)
{
if(out>len){
cout<<"输出的元素大于栈内元素个数!!!"<<endl;
}
else{
LkStack Tem;
cout<<"出栈元素为:"<<endl;
for(int i = 0;i<out;i++){//出栈的元素个数
Tem = top;
cout<<Tem->data<<" ";
top = Tem->next;
}
cout<<endl;
free(Tem);
}
}
main()
{
int len,out;
cout<<"请确定链栈的长度:"<<endl;
while(cin>>len){
LkStack top = NULL;//链栈没有头结点,直接new一个指针为头指针
CreateLkstack(top,len);
cout<<"请确定要出栈几个元素:"<<endl;
cin>>out;
PopStack(top,out,len);
system("pause");
cout<<"请确定链栈的长度:"<<endl;
}
}//循环队列在顺序存储下的表示
#include<iostream>
using namespace std;
typedef struct
{
int *base;//指向数组的首元素
int front;//头指针(并非真正的指针变量,用来表示下标的位置)
int rear;//尾指针(同上)
}SqQuene;
void InsitSqQuene(SqQuene &Q,int &n)
{
Q.base = new int[n];
Q.front = Q.rear = 0;
}
/*
1.循环队列在表尾进行插入,在表头进行删除;先进的先出,即插入时rear动,删除时front动
2.循环队列的特点是逻辑上首尾相连,用取模(%n求余数)的方式来表示要插入元素的位置
3.循环队列牺牲一个单位的空间来区别队列的空与满
(1)如果队列为空,则Q.rear == Q.front
(2)如果队列为满,则(Q.rear+1)%n == Q.front
4.求队列长度:(Q.rear - Q.front + n)%n
(1)可能的情况是rear指针已经循环到front指针的下方,所以要加上总长度n
(2)如果rear正常的在front的上方,加上n也会被%取余给过滤掉
*/
void InsertSqQuene(SqQuene &Q,int &n)
{
if((Q.rear+1)%n == Q.front){//判断队列是否已经满了,满了就不能继续存放数据了
cout<<"队列已满!!!"<<endl;
}
else{
cout<<"请输入要插入的数据:";
cin>>Q.base[Q.rear];//先把数据输入
Q.rear = (Q.rear+1)%n;
}
cout<<"此时队列里有元素个数为:"<<(Q.rear-Q.front +n)%n<<endl;
}
void DeleteSqQuene(SqQuene &Q,int &n)
{
if(Q.rear == Q.front){
cout<<"队列为空!!!"<<endl;
}
else{
Q.front = (Q.front+1)%n;//删除即把元素位置往前进一个单位,并不是把之前的元素空间释放,同时rear指针不动
}
cout<<"此时队列里有元素个数为:"<<(Q.rear-Q.front +n)%n<<endl;
}
void PrintDSqQuene(SqQuene &Q,int &n)
{
if(Q.rear != Q.front){
cout<<"队列里的元素为:";
int Tem = Q.front;//Tem为中间变量,输出完毕后把front的值回复为初始状态
while(Q.rear != Q.front){
cout<<Q.base[Q.front]<<" ";
Q.front = (Q.front +1)%n;
}
Q.front = Tem;
}
cout<<endl;
}
main(){
int n,flag;
cout<<"请确定队列的长度:";
while(cin>>n){
SqQuene Q;
InsitSqQuene(Q,n);
cout<<"请确定进行插入还是删除,输入1为插入,输入2为删除,输入3为输出队列里现有的元素!"<<endl;
while(cin>>flag){
if(flag == 1){
InsertSqQuene(Q,n);
}
else if(flag==2){
DeleteSqQuene(Q,n);
}
else if(flag == 3){
PrintDSqQuene(Q,n);
}
cout<<"请确定进行插入还是删除,输入1为插入,输入2为删除,输入3为输出队列里现有的元素!"<<endl;
}
//PrintDSqQuene(Q,n);
system("pause");
cout<<"请确定队列的长度:";
}
}//入栈出栈的顺序存储形式
#include<iostream>
#define MAXSIZE 100
using namespace std;
typedef struct
{
int *top;
int *base;
int size;
}Sqstack;
void InsitStack(Sqstack &S)
{
S.base = new int[MAXSIZE];//开辟数组空间
if(!S.base){
cout<<"开辟空间失败!!!"<<endl;
}
else{//初始化栈的头指针,尾指针和长度
S.top = S.base;
S.size = 0;
}
}
void PushStack(Sqstack &S,int &size)
{
if(S.top - S.base == MAXSIZE){
cout<<"栈空间已满。"<<endl;
}
else{
cout<<"请输入数据:"<<endl;
for(int i = 0;i<size;i++){//通过top指针所指地址开对栈空间压入元素
cin>>*S.top;
S.top++;
S.size++;
}
}
cout<<"此时栈中元素个数为:"<<S.size<<endl;
}
void PopStack(Sqstack &S,int &size)
{
if(S.top <= S.base){
cout<<"栈中无元素!!!"<<endl;
}
else{
int flag = 0;//flag控制空格输出
cout<<"栈中的元素如下:"<<endl;
for(int i = 0;i<size;i++){
if(flag == 0){
S.top--;
cout<<*S.top;
S.size--;
flag = 1;
}
else{
S.top--;
cout<<" "<<*S.top;
S.size--;
}
}
cout<<endl;
}
}
main()
{
int size;
cout<<"请确定栈的长度(100之内):"<<endl;
while(cin>>size){
Sqstack S;
InsitStack(S);
PushStack(S,size);
PopStack(S,size);
cout<<"请确定栈的长度(100之内):"<<endl;
}
}字符串:
//KMP算法
#include <iostream>
using namespace std;
const int N = 100010 , M = 1000010;
char a[N] , b[M];
int n , m;
int ne[N];
int main()
{
//此时将字符串从下标为1开始进行输入
cin >> n >> a + 1 >> m >> b + 1;
//求ne[]数组
for (int i = 2 , j = 0 ; i <= n ; i ++)
{
while (j && a[j + 1] != a[i]) j = ne[j];
if (a[j + 1] == a[i]) j ++;
ne[i] = j;
}
//进行kmp
for (int i = 1 , j = 0 ; i <= m ; i ++)
{//此时i表示的是b数组的下标
while (j && a[j + 1] != b[i]) j = ne[j];
if (a[j + 1] == b[i]) j ++;
if (j == n)
{
cout << i - j << ' ';
j = ne[j];
}
cout << endl;
return 0;
}//BF算法:
#include<iostream>
#include<String.h>
#define MAX 100
using namespace std;
void CompareChar(char ma[],char ch[])
{
int len1 = strlen(ma);
int len2 = strlen(ch);
//cout<<len1<<" "<<len2;
int i = 0,j = 0;
while(i<len1 && j<len2){
if(ma[i] == ch[j]){//主串和字符串依次匹配下一个字符
i++;
j++;
}
else{//主串,子串指针回溯重新开始下一次匹配
i = i-j+1;//主串从上次比对的地方重新开始匹配(因为字符从0开始进行比较,所以当不满足条件的时候,i减去已经比较的j个字符个数,再加1往前一个)
j = 0;//子串从第一个字符重新开始匹配
}
}
if(j == len2){//如果匹配成功,则子串全部对比完成
cout<<"匹配成功,从主串中第"<<i-len2+1<<"个字符开始为匹配子串!"<<endl;
}
else{
cout<<"匹配不成功!"<<endl;
}
}
main()
{
while(1){
char ma[MAX],ch[MAX];//一个主串,一个子串
cout<<"请输入主串:";
gets(ma);
cout<<"请输入子串:";
gets(ch);
CompareChar(ma,ch);
}
system("pause");
}图:
//法1 Dijkstra算法
求起始点1到N的最短路径.
Input
多组测试数据,对于每组数据
第一行是两个整数N, M。分别代表定点的数个和边的关系的个数。
从第二行至M+1行,每行三个整数,start, end, value。代表,节点start,节点end之间有一条长度为value的无向边。求1到N的最短路径。
(M, N, start, end, value < 100)
Output
对于每组测试数据,输出一个整数result,代表1至N的最短路径。
代码如下:
#include<iostream>
#define MAX 101
using namespace std;
const int N = 80;
int dist[N];
bool st[N];
typedef struct
{
int arcs[N][N];
int vexnum,arcnum;
}AMGrap;
void CreateGrap(AMGrap &G,int &m,int &n)
{
int v1,v2,w,i,j;
G.vexnum = m;
G.arcnum = n;
for(i = 1; i <= G.vexnum; i++){//初始化邻接矩阵
for(j = 1; j <= G.vexnum; j++){
if(i == j) {G.arcs[i][j] = 0;}
else {G.arcs[i][j] = MAX;}
}
}
for(i = 0; i < G.arcnum; i++){//构建无向网
cin>>v1>>v2>>w;
G.arcs[v1][v2] = w;
G.arcs[v2][v1] = w;
}
}
bool Judge(int &n)
{
for(int i = 1; i <= n; i++){//只要st集合中不等于顶点全集,就返回true
if(!st[i]) return true;
}
return false;
}
void DjsGrap(AMGrap &G)
{
int v = 1,i,j,min;
for(i = 1; i <= G.vexnum; i++) dist[i] = G.arcs[v][i];
dist[v] = 0;
for(i = 1; i <= G.vexnum; i++) st[i] = false;
st[v] = true;
while(Judge(G.vexnum)){
j = 1,min = MAX;
for(i = 1; i <= G.vexnum; i++){
if(!st[i]){
if(min >= dist[i]) {min = dist[i]; j = i;}
}
}
st[j] = true;//j加入st集合
for(i = 1; i <= G.vexnum; i++){
if(!st[i]){
if(dist[i] >= dist[j] + G.arcs[j][i]) dist[i] = dist[j] + G.arcs[j][i];
}
}
}
}
int main()
{
AMGrap G;
int m,n;
while(cin>>m>>n){
CreateGrap(G,m,n);
DjsGrap(G);
cout<<dist[G.vexnum]<<endl;
}
}//法2:
//Floyd算法 找最短路径,同时记录了最短路径
//邻接矩阵
#include<iostream>
#include<stack>
using namespace std;
#define MaxVnum 100 //顶点数最大值
const int INF = 1e7; //无穷大
int dist[MaxVnum][MaxVnum]; //某个点最短路径数组
int p[MaxVnum][MaxVnum]; //某个点的前驱数组
bool flag[MaxVnum]; //某个顶点已经加入S集合中
typedef struct {
int Vex[MaxVnum];
int Edge[MaxVnum][MaxVnum];
int vennum,edgenum; //真实的顶点个数和边个数
}AMGraph;
void CreateGraph(AMGraph &G, int n, int m)
{
G.vennum = n;
G.edgenum = m;
for(int i = 0; i < G.vennum; i++){
G.Vex[i] = i + 1;
}
//初始化过程
for(int i = 0; i < G.vennum; i++){
for(int j = 0; j < G.vennum; j++){
if(i != j){
G.Edge[i][j] = INF;
} else{
G.Edge[i][j] = 0;
}
}
}
int w;
// cout<<"请输入哪两点和其权值"<<endl;
int u,v;
while(G.edgenum--){
cin>>u>>v>>w; //a b 权值
int i = u - 1; //获取顶点下标
int j = v - 1; //获取顶点下标
if(i != -1 && j != -1){ //i j找到了位置
G.Edge[i][j] = w;
} else{
cout<<"请重新输入边的顶点信息"<<endl;
G.edgenum++; //当输入错误后把while条件加回来否则死循环 本次输入不算
}
}
}
void Floyd(AMGraph G) //找到i和j之间的最短路径
{
for(int i = 0; i < G.vennum; i++){
for(int j = 0; j < G.vennum; j++){
dist[i][j] = G.Edge[i][j]; //初始化
if(dist[i][j] < INF && i != j){
p[i][j] = i; //如果i和j之间有弧 则为i
} else{
p[i][j] = -1; //如果i和j之间无弧 则为-1
}
}
}
for(int k = 0; k < G.vennum; k++){
for(int i = 0; i < G.vennum; i++){
for(int j = 0; j < G.vennum; j++){
if(dist[i][k] + dist[k][j] < dist[i][j]){ //从i经k到j的一条路径更短
dist[i][j] = dist[i][k] + dist[k][j]; //更新dist[i][j]
p[i][j] = p[k][j]; //更新前驱
}
}
}
}
}
int main()
{
AMGraph G;
int n,m;
while(cin>>n>>m){
CreateGraph(G,n,m);
Floyd(G);
cout<<dist[0][G.vennum - 1]<<endl;
}
return 0;
}图的邻接矩阵形式下的DFS和BFS:
//邻接矩阵存储下的无向网的创建及DFS遍历(深度优先算法)BFS遍历(广度优先算法)
#include<iostream>
#define MaxNum 100//最大顶点数
#define MaxInt -1//表示极大值∞
using namespace std;
typedef struct
{
int vexs[MaxNum]; //顶点表
int arcs[MaxNum][MaxNum]; //邻接矩阵表
int vexnum,arcnum; //图的顶点数和边数
}AMGrap;
void CreateGrap(AMGrap &G)//创建无向网图
{
int v1,v2,w,i,j;
cout<<"请输入图的顶点数和边数:";
cin>>G.vexnum>>G.arcnum; //输入图的顶点数和边数
for(i = 0; i < G.vexnum; i++) G.vexs[i] = i;//输入各个顶点的信息
for(i = 0; i < G.vexnum; i++){//初始化邻接矩阵
for(j = 0; j < G.vexnum; j++){
G.arcs[i][j] = MaxInt; //每个边的权值都为无穷大
}
}
cout<<"请输入边的信息及权值:"<<endl;
for(i = 0; i<G.arcnum; i++){
cin>>v1>>v2>>w; //输入边所依附的顶点和边对应的权值
G.arcs[v1][v2] = w; //<v1,v2> = w
G.arcs[v2][v1] = G.arcs[v1][v2]; //邻接矩阵中<v1,v2>的对称边<v2,v1>的权值为w
}
}
void PrintfGrap(AMGrap &G)
{
cout<<"邻接矩阵为:"<<endl;
for(int i = 0; i < G.vexnum; i++){
for(int j = 0; j < G.vexnum; j++){
cout<<G.arcs[i][j]<<" ";
}
cout<<endl;
}
}
void InsitVisited(AMGrap &G,int visited[])
{
for(int i = 0; i < G.vexnum; i++) visited[i] = 0;//初始化辅助数组都为0,表示都初始时未被访问
}
void DFSGrap(AMGrap &G,int &v,int visited[])
{
cout<<v<<" ";
visited[v] = 1; //在辅助数组中标记该顶点已经访问过
for(int i = 0; i < G.vexnum; i++){ //依次检查邻接矩阵中v行中未曾访问的邻接点
if((G.arcs[v][i] != -1) && (visited[i] == 0)){//i是v的邻接点,若未曾访问,则调用递归
DFSGrap(G,i,visited);
}
}
}
int main()
{
AMGrap G;
CreateGrap(G);
PrintfGrap(G);
int v,visited[G.vexnum];
InsitVisited(G,visited);
cout<<"请输入要从哪个顶点开始遍历:";
cin>>v;
cout<<"DFS序列为:";
DFSGrap(G,v,visited);
system("pause");
}/*邻接表的输入输出示例:
请输入顶点数和边数:4 4
请输入边的信息及权值:
0 1 1
0 2 4
0 3 5
1 3 1
创建成功!
邻接表为:
0 -> 3 -> 2 -> 1
1 -> 3 -> 0
2 -> 0
3 -> 1 -> 0
请输入要从哪个顶点开始遍历:2
DFS序列为:2 0 3 1
BFS序列为:2 0 3 1
*/
//邻接表存储下的无向网的创建及DFS遍历(深度优先算法)BFS遍历(广度优先算法)
#include<iostream>
#define MaxNum 100 //最大顶点数
using namespace std;
typedef struct ArcNode//边结点
{
int adjvex; //顶点的邻接点在顶点数组中的下标位置
struct ArcNode * nextarc; //指向下一个与数组中元素是邻接点的指针
int info; //节点信息,比如权值等
}ArcNode,*PNode;
typedef struct//顶点结构
{
int data; //顶点信息,通常没有用;除非用字符等表示顶点而不是下标时,用来存储符号等
PNode firstarc;
}VNode,AdjList[MaxNum]; //创建顶点数组,AdjList表示邻接表类型
typedef struct//图的结构
{
AdjList vertices; //定义一个结构体数组实体,来存储顶点信息
int vexnum,arcnum; //顶点数和边数
}ALGrap;
typedef struct
{
int *base,front,rear,size;
}SqQuene;//循环队列结构类型定义
void CreateGrap(ALGrap &G)
{
int v1,v2,w,i;
cout<<"请输入顶点数和边数:";
cin>>G.vexnum>>G.arcnum;
for(i = 0; i < G.vexnum; i++){
G.vertices[i].data = i; //初始表结点,用0,1,2,3...表示
G.vertices[i].firstarc = NULL;//将表中顶点的firstarc初始为空
}
cout<<"请输入边的信息及权值:"<<endl;
for(i = 0; i < G.arcnum; i++){
cin>>v1>>v2>>w; //输入边的两个点及边的权值
PNode p1 = new ArcNode();//创建一个边结点,头插法
p1->adjvex = v2;
p1->nextarc = G.vertices[v1].firstarc;//将新结点p用头插法插入vi的边表中,如果输入边时从小到大,输出会是从大到小
G.vertices[v1].firstarc = p1;
PNode p2 = new ArcNode();//无向网中有对称的边结点,在有向网或有向图中不用进行以下步骤
p2->adjvex = v1;
p2->nextarc = G.vertices[v2].firstarc;
G.vertices[v2].firstarc = p2;
}
cout<<"创建成功!"<<endl;
return;
}
void PrintfGrap(ALGrap &G)
{
cout<<"邻接表为:"<<endl;
for(int i = 0; i < G.vexnum; i++){
PNode p = G.vertices[i].firstarc;//定义辅助结点指针初始指向该行链表的头结点
cout<<i;
while(p){
cout<<" -> "<<p->adjvex;
p = p->nextarc;
}
cout<<endl;
}
}
void InsitVisited(int visited[],ALGrap &G)
{
for(int i = 0; i < G.vexnum; i++) visited[i] = 0;//初始化辅助数组
}
void DFSGrap(ALGrap &G,int v,int visited[])
{
cout<<v<<" ";
visited[v] = 1;
PNode p = G.vertices[v].firstarc; //定义新的结点指针,对第v行链表进行从头开始的检查
while(p){
if((p != NULL) && (visited[p->adjvex] == 0)) DFSGrap(G,p->adjvex,visited);//如果该结点不为空并且该结点对应的邻接顶点未被访问过,进行递归
p = p->nextarc;
}
}
void InsitSqQuene(SqQuene &Q,ALGrap &G)//循环队列初始化
{
Q.base = new int[G.vexnum];
Q.front = Q.rear = Q.size = 0;
}
void InsertSqQuene(SqQuene &Q,int &v,ALGrap G)//入队
{
if((Q.rear + 1) % G.vexnum == Q.front) return;
//cout<<"("<<v<<")"<<endl;
Q.base[Q.rear] = v;//插入队列中元素时用rear指针来控制插入
Q.rear = (Q.rear + 1) % G.vexnum;
Q.size++;
}
int DeleteSqQuene(SqQuene &Q,ALGrap G)//队头元素出队并作为返回值返回
{
int tem = Q.base[Q.front];
//cout<<"["<<tem<<"]"<<endl;
Q.front = (Q.front + 1) % G.vexnum;
Q.size--;
return tem;
}
void BFSGrap(ALGrap &G,int v,int visited[],SqQuene &Q)
{
cout<<v<<" ";
visited[v] = 1;
InsitSqQuene(Q,G); //辅助循环队列初始化置空
InsertSqQuene(Q,v,G);//v进队
while(Q.size != 0){
int u = DeleteSqQuene(Q,G);//队头元素出队并置为u
PNode p = new ArcNode();
p = G.vertices[u].firstarc;
while(p){//在第u行依次找到未访问结点,while语句是用来控制循环,if循环控制是否进行该操作
int w = p->adjvex;
if(!visited[w]){
cout<<p->adjvex<<" ";
visited[p->adjvex] = 1;
InsertSqQuene(Q,p->adjvex,G);
}
p = p->nextarc;
}
free(p);
}
}
int main()
{
ALGrap G;
SqQuene Q;
CreateGrap(G);
PrintfGrap(G);
int v,visited[G.vexnum];
cout<<"请输入要从哪个顶点开始遍历:";
cin>>v;
InsitVisited(visited,G);
cout<<"DFS序列为:";
DFSGrap(G,v,visited);
cout<<endl;
InsitVisited(visited,G);
cout<<"BFS序列为:";
BFSGrap(G,v,visited,Q);
cout<<endl;
system("pause");
}二叉树:
//链式存储之下的二叉树的先序建立方式和遍历方式(先序,中序,后序)计算数的深度,叶子结点,节点数。
#include<iostream>
#include<string.h>
using namespace std;
int n;
typedef struct Node
{
char data;
Node *lchild,*rchild;
}LkNode,*BiTree;
void CreateBiTree(BiTree &T)//手动建立一个二叉树,再根据节点顺序输入(先序建立以个二叉树)
{
char ch;
cin>>ch;
if(ch == '0'){
T = NULL;
return;
}
else{
T = new LkNode();
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
void PreOrderTraverse(BiTree &T)//先序遍历(先根遍历)
{
if(T != NULL){
cout<<T->data<<" ";
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
else return;
}
void MidOrderTraverse(BiTree &T)
{
if(T != NULL){
PreOrderTraverse(T->lchild);
cout<<T->data<<" ";
PreOrderTraverse(T->rchild);
}
else return;
}
void LastOrderTraverse(BiTree &T)
{
if(T != NULL){
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
cout<<T->data<<" ";
}
else return;
}
int Depth(BiTree T)//左右子树本身的深度加1
{
if(!T) return 0;
else{
int m,n;
m = Depth(T->lchild);//左子树深度
n = Depth(T->rchild);//右子树深度
if(m > n) return m+1;
else return n+1;
}
}
int LeafCount(BiTree T)
{
if(!T) return 0;
else{
if(!T->lchild && !T->rchild) return 1;//叶子即为根
else return LeafCount(T->lchild) + LeafCount(T->rchild);
//计算左子树和右子树的叶子节点之和
}
}
int NodeCount(BiTree T)
{
if(!T) return 0;
else return NodeCount(T->lchild) + NodeCount(T->rchild) + 1;
}
//交换左右子树的所有节点2
void SwapBiTree(BiTree T){
BiTree tem = new LkNode();
if(T){
tem = T->rchild;
T->rchild = T->lchild;
T->lchild = tem;
SwapBiTree(T->lchild);
SwapBiTree(T->rchild);
}
else return;
}
//实现复制二叉树
void CopyBiTree(BiTree T,BiTree &T2)
{
T2 = new LkNode();
if(T){
T2->data = T->data;
CopyBiTree(T->lchild , T2->lchild);
CopyBiTree(T->rchild , T2->rchild);
}
else{
T2 = NULL;
return;
}
}
main()
{
while(1){
cout<<"请输入节点:";
BiTree root = NULL;//创建一个根节点开始二叉树的建立
CreateBiTree(root);
cout<<"按照先序次序输入的二叉树创建成功!"<<endl;
cout<<"先序遍历的顺序为:";
PreOrderTraverse(root);
cout<<endl;
cout<<"中序遍历的顺序为:";
MidOrderTraverse(root);
cout<<endl;
cout<<"后序遍历的顺序为:";
LastOrderTraverse(root);
cout<<endl;
cout<<"此二叉树的深度为:"<<Depth(root)<<endl;
cout<<"此二叉树的叶子结点为:"<<LeafCount(root)<<endl;
cout<<"此二叉树的节点数为:"<<NodeCount(root)<<endl;
}
}//完全二叉树的创建
#include<iostream>
#define MAX 1025
using namespace std;
int n;
void PreOrderTraverse(int Tree[],int i)
{
if(i>n){//共n个节点,递归的条件是不会超过数组最大节点数
return;
}
else{
cout<<Tree[i-1]<<" ";
PreOrderTraverse(Tree,2*i);
PreOrderTraverse(Tree,(2*i)+1);
}
}
main()
{
int Tree[MAX];
while(cin>>n){
for(int i = 0;i<n;i++){
Tree[i] = i+1;
}
PreOrderTraverse(Tree,1);
cout<<endl;
}
}//最小生成树(基本都对应的无向图)--普利姆(Prim)算法--朴素版(对应为稠密图)
/*
步骤:
1.初始化邻接矩阵和dist数组
2.找到集合外距离集合最近的点并把它赋值给t,用t更新其余顶点到集合的距离
3.把t加到集合当中去,表明t成为最小生成树的一个顶点;继续迭代进行2
*/
#include<iostream>
#include<algorithm>
#include<cstring>
#define MAX 0x3f3f3f3f
using namespace std;
const int N = 100 ;
int n,m;
int g[N][N];
int dist[N];
bool st[N];//st数组定义后数组元素默认都为0,相当于false
//核心模板
int prim()
{
memset(dist , 0x3f , sizeof dist);//初始化dist数组为无穷大
int res = 0;//rest记录最小生成树的权值之和
for(int i = 0;i < n; i++){//n次循环,加入n个顶点
int t = -1;
for(int j = 1;j <= n; j++){//从顶点1开始构造最小生成树
if(!st[j] && (t == -1 || dist[t] > dist[j])) t = j;//找出每次更新后的最小权值边
}
if(i && dist[t] == MAX) return MAX;//此时说明图为非连通图,无法生成最小生成树
if(i) res += dist[t];
for(int j = 1; j <= n; j++) dist[j] = min(dist[j],g[t][j]);//找到一条生成树的边后更新其他店到集合内顶点的距离,为累积更新
st[t] = true;
}
return res;
}
int main()
{
cout<<"请输入边数和节点数:";
cin>>n>>m;
memset(g,0x37,sizeof g);//初始化邻接矩阵中所有元素为最大值
cout<<"请输入边的邻接点及权值:"<<endl;
while(m--){
int v1,v2,w;
cin>>v1>>v2>>w;
g[v1][v2] = g[v2][v1] = min(g[v1][v2] , w);//边的权值要么是输入边中最小的,要么是无穷大
}
int t = prim();
if(t == MAX) cout<<"impossible!"<<endl;
else cout<<t<<endl;
system("pause");
}//二叉排序树:
#include <iostream>
using namespace std;
typedef struct tree
{
int count;
struct tree* pleft;//定义一个左指针
struct tree* pright;//定义一个右指针
}Tree , *TreeNode;
void SetTree(TreeNode& pTree, int num)
{
if (pTree == NULL)
{
pTree = (TreeNode)malloc(sizeof (Tree));
pTree->count = num;
pTree->pleft = NULL;
pTree->pright = NULL;
}
else
{
TreeNode pTemp = pTree;
while (1)
{
if (pTemp->count > num)
{
if (pTemp->pleft != NULL)
pTemp = pTemp->pleft;
else
{
TreeNode pTemp1 = (TreeNode)malloc(sizeof (Tree));
pTemp1->count = num;
pTemp1->pleft = NULL;
pTemp1->pright = NULL;
pTemp->pleft = pTemp1;
return;
}
}
else if (pTemp->count < num)
{
if (pTemp->pright != NULL)
{
pTemp = pTemp->pright;
}
else
{
TreeNode pTemp1 = (TreeNode)malloc(sizeof (Tree));//开辟一个结点
pTemp1->count = num;
pTemp1->pleft = NULL;
pTemp1->pright = NULL;
pTemp->pright = pTemp1;
return;
}
}
else if (pTemp->count == num)
{
cout << "产生重复数字" << endl;
return;
}
}
}
}
void FindDel(TreeNode pTree, int num, TreeNode& pTemp, TreeNode& pfather)
{
pTemp = pTree;
while (pTemp){
if (pTemp->count == num){//此时表示当前根节点就是num
cout << "找到当前要找的数所对应的结点" << endl;
return;
}
else if (pTemp->count > num){
pfather = pTemp;
pTemp = pTemp->pleft;
}
else if (pTemp->count < num){
pfather = pTemp;
pTemp = pTemp->pright;//将pTemp指向其右子树
}
}
cout << "该数值在当前的二叉搜索树中查找失败" << endl;
return;
}
void FindMin(TreeNode& pTree, int num)
{
if (pTree == NULL) return;
TreeNode pTemp = NULL;
TreeNode pfather = NULL;
FindDel(pTree, num, pTemp, pfather);
if (pTemp == NULL) return;
TreeNode pMark = NULL;
if (pTemp->pleft != NULL && pTemp->pright != NULL)
{//此时找到的结点的左右子树都不是空的情况
pMark = pTemp;
pfather = pTemp;
pTemp = pTemp->pleft;
while (pTemp->pright){
pfather = pTemp;
pTemp = pTemp->pright;
}
pMark->count = pTemp->count;
}
if (pfather == NULL){
if (pTemp->pleft)
{
pTree = pTemp->pleft;//此时将根节点的指针指向根节点的左子树
//也就是将根节点删除了
}
else if (pTemp->pright){
pTree = pTemp->pright;
}
else{//此时表示这个根节点的左子树和右子树都是空的
pTree = NULL;//将根节点指针置空
free(pTemp);//将pTemp结点开辟的空间删除
pTemp = NULL;//将pTemp指针置空
return;
}
}
if (pfather->pleft == pTemp){
if (pTemp->pleft)
pfather->pleft = pTemp->pleft;
else
pfather->pleft = pTemp->pright;
}
else{
if (pTemp->pleft)
pfather->pright = pTemp->pleft;
else
pfather->pright = pTemp->pright;
}
free(pTemp);
pTemp = NULL;
return;
}
void GetTree(TreeNode pTree)
{
if (pTree == NULL)
return;
GetTree(pTree->pleft);
cout << pTree->count << ' ';
GetTree(pTree->pright);
}
int main()
{
TreeNode pTree = NULL;
int n, num;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> num;
SetTree(pTree, num);
}
GetTree(pTree);
cout << endl;
cin >> num;
cout<<"删除该节点后中序遍历序列为:";
FindMin(pTree, num);
GetTree(pTree);
cout << endl;
system("pause");
return 0;
}二叉平衡树的删除:
//右旋
void RightTurn(Tree **pTree)
{
if(*pTree == NULL||(*pTree)->pLeft == NULL) return;
Tree *pNode = *pTree; //A
Tree *pMark = (*pTree)->pLeft; //B
//三个孩子
pNode->pLeft = pMark->pRight;
pMark->pRight = pNode;
if(pNode->pFather != NULL)
{
if(pNode == pNode->pFather->pLeft)
{
pNode->pFather->pLeft = pMark;
}
else
pNode->pFather->pRight = pMark;
}
else
{
//B成为新根
*pTree = pMark;
}
/三个父亲关系
if(pNode->pLeft != NULL)
{
pNode->pLeft->pFather = pNode;
}
pMark->pFather = pNode->pFather;
pNode->pFather = pMark;
}
//左旋
void LeftTurn(Tree **pTree)
{
if(*pTree == NULL||(*pTree)->pRight == NULL) return;
Tree *pNode = *pTree; //A
Tree *pMark = (*pTree)->pRight; //C
//三个孩子
pNode->pRight = pMark->pLeft;
pMark->pLeft = pNode;
if(pNode->pFather != NULL)
{
if(pNode == pNode->pFather->pLeft)
pNode->pFather->pLeft = pMark;
else
pNode->pFather->pRight = pMark;
}
else
{
//C成为新根
*pTree = pMark;
}
//三个父亲
if(pNode->pRight != NULL)
pNode->pRight->pFather = pNode;
pMark->pFather = pNode->pFather;
pNode->pFather = pMark;
}查找算法:
//基本查找算法
#include<iostream>
using namespace std;
const int N = 101;//数据个数最多为100
int n,key,a[N];//定义数据数组,n是数据个数,key是要查找的值,a[N]是顺序表
void SearchSeq()//顺序查找,数组次序无要求
{
for(int i = n;i > 0 ; i--) {
if(a[i] == key) {cout<<"该元素的位置为:"<<i<<endl; return ;}
}
cout<<"无该记录"<<endl;
return;
}
void Search0()//哨兵查找,数组次序无要求
{
a[0] = key;
int i;//记录查找到的元素位置
for(i = n ; a[i] != key ; --i);//当for循环没有循环语句时,结尾要加; ,锁定循环结束之后i的值
if(i == 0) cout<<"无该记录"<<endl;
else cout<<"该记录的位置为:"<<i<<endl;
}
void SearchHalf()//折半查找(二分查找),要求数列必须是有序的
{
int low = 1,high = n,mid;
while(low <= high){
mid = (low + high) / 2;//每次查找跟mid比较,mid就是中间值
if(a[mid] == key) {cout<<"该元素的位置为:"<<mid<<endl; return;}
else if(key < a[mid]) high = mid - 1;
else low = mid + 1;
}
cout<<"无该记录"<<endl;
}
int main()
{
cout<<"请输入元素个数及数据记录:";
cin>>n;
for(int i = 1; i <= n;i++) cin>>a[i];//从1开始输入数据
cout<<"请输入要查找的值:";
cin>>key;
SearchSeq();
Search0();
SearchHalf();
system("pause");
}
/* i--是先赋值再--
--i是先--后赋值
*/排序:
//归并排序--分治(双指针算法)由小到大进行排序
基本思想:
1.确定中间的分界点:mid = (l+r)/2
2.把数组从中间分成两部分,递归排序左右两部分
3.归并--合二为一
*/
#include<iostream>
using namespace std;
const int N = 1000010;
int n;
int q[N],tem[N];
void merge_sort(int q[],int l,int r)
{
if(l >= r) return;
int mid = l + r >> 1;//相当于int mid = (l+r)/2
merge_sort(q,l,mid), merge_sort(q,mid + 1,r);
int k = 0,i = l,j = mid + 1;
while(i <= mid && j <= r){
if (q[i] <= q[j]) tem[k++] = q[i++];
else tem[k++] = q[j++];
}
while(i <= mid) tem[k++] = q[i++];
while(j <= r) tem[k++] = q[j++];
for(i = l,j = 0;i <= r;i++,j++) q[i] = tem[j];
}
int main()
{
scanf("%d",&n);
for(int i = 0;i < n;i++ ) scanf("%d" , &q[i]);
merge_sort(q,0,n-1);
for(int i = 0;i < n;i++ ) printf("%d " , q[i]);
system("pause");
return 0;
}//插入排序
#include<iostream>
#include<math.h>
using namespace std;
const int N = 1e6 + 10;
int n;
int q[N];
//核心代码模板
void quick_sort(int q[], int l, int r)//l和r分别是指向左右的移动指针,当l>=r时,说明已经区间调整完毕
{
if(l >= r) return;//判断当前区间只有一个数的时候就不用排序了
int x = q[l], i = l-1, j = r+1;//
while(i < j){//两个指针没有相遇或穿过
do i++; while(q[i] < x);//左指针向右移,++(若想从大到小排序,只需改变这两句的比较符号)
do j--; while(q[j] > x);//右指针向左移,--
if(i<j) swap(q[i],q[j]);//当两个指针都停止时,进行两个指针所指元素的值得对换,对换之后判断i<j,继续调整区间
}
quick_sort(q, l, j);
quick_sort(q, j+1, r);
}
int main()
{
scanf("%d",&n);
for(int i = 0; i < n; i ++ ){
scanf("%d",&q[i]);
}
quick_sort(q,0,n-1);
for(int i = 0; i < n; i++ ){
printf("%d ",q[i]);
}
system("pause");
return 0;
}