(第三章、第二章)数据结构总复习+错题+一些不清楚的点。
第三章栈和队列
-
慕课:
- 递归需要终止部分和递归部分
- 递归比非递归更浪费空间且更慢。
栈混洗的判断,需要的栈的最大容量。
- 手动判断即可。
各种算法
1.舞伴问题(队列)
- 还是比较简单的,注意字符串和字符的接收之间的吸收
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<queue>
#include<stack>
using namespace std;
typedef struct
{
char name[20];
char sex;
}Datatype;
void DancerFriends(Datatype dancer[20])
{
queue<Datatype>man;
queue<Datatype>woman;
for (int i = 0; i < 9; i++)
{
if (dancer[i].sex == 'F')woman.push(dancer[i]);
else man.push(dancer[i]);
}
while (!man.empty() && !woman.empty())
{
printf("%s %s\n", woman.front().name, man.front().name);
man.pop();
woman.pop();
}
while (!man.empty())
{
printf("%s\n", man.front().name);
man.pop();
}
while (!woman.empty())
{
printf("%s\n", woman.front().name);
}
}
int main()
{
Datatype dancer[20];//F为女,M为男
for (int i = 0; i < 9; i++)
{
scanf("%s", dancer[i].name);
getchar();
scanf("%c", &dancer[i].sex);
getchar();//这个可有可不有
}
DancerFriends(dancer);
return 0;
}
/*
李敏浩 M
李钟硕 M
高欣雅 F
吴彦祖 M
王思聪 M
张甜源 F
张智霖 M
许丹丹 F
马小云 F
*/
2.回文问题(栈和队列)
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<queue>
#include<stack>
using namespace std;
void ChargeHuiWen(char* string)
{
stack<char>lstack;
queue<char>lqueue;
int len = strlen(string);
int i = 0;
for (i; i < len; i++)
{
lstack.push(string[i]);
lqueue.push(string[i]);
}
while (!lstack.empty() && !lqueue.empty())
{
if (lstack.top() == lqueue.front())
{
lstack.pop();
lqueue.pop();
}
else
{
printf("NO!\n");
return;
}
}
printf("OK!\n");
}
int main()
{
char string[20];
scanf("%s", string);
ChargeHuiWen(string);
return 0;
}
3.括号匹配(栈)
- 注意:与回文问题不一样,只是要求括号的闭合。
- {{{((()))}}}:这个不是回文 ,{()()()}:这个不是回文,但两个都是ture.(不知道为啥总想把第一个当作回文,但不是啊!!)
😿 - 思路:左括号入栈,右括号比较,比较后出栈。
- 别忘了考虑最后有剩余的’(‘或’)’
- 注意用右括号与左括号对应时,不要用输入的右括号与栈里的左括号比啊!。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<queue>
#include<stack>
using namespace std;
int main()
{
char ch;
scanf("%c", &ch);
stack<char>lstack;
while (ch != '#')
{
switch (ch)
{
case'[':
case'(':
case'{':
lstack.push(ch);
break;
case')':
if (!lstack.empty())
{
if ('(' == lstack.top())
{
lstack.pop();
}
else
{
printf("NO!\n");
return 0;
}
}
else
{
printf("NO!\n");
return 0;
}
break;
case']':
if (!lstack.empty())
{
if ('[' == lstack.top())
{
lstack.pop();
}
else
{
printf("NO!\n");
return 0;
}
}
else
{
printf("NO!\n");
return 0;
}
break;
case'}':
if (!lstack.empty())
{
if ('{' == lstack.top())
{
lstack.pop();
}
else
{
printf("NO!\n");
return 0;
}
}
else//最后剩余右')'
{
printf("NO!\n");
return 0;
}
break;
}
scanf("%c", &ch);//别忘了。。。
}
if (!lstack.empty())//最后有剩余的左括号
printf("NO!\n");
else printf("YES!\n");
return 0;
}
/*测试用例
()()()#
({[]})#
((()))#
({}{})#
({}{}))#
(({}{})#
*/
4.十进制转十六进制(栈)
- 跟10进制转2进制一个原理,一直短除取余,最后倒过来写。
- 注意pop,注意除。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<queue>
#include<stack>
using namespace std;
int main()
{
int temp;
scanf("%d", &temp);
stack<int>lstack;
while (temp != 0)
{
lstack.push(temp % 16);
temp /= 16;
}
while (!lstack.empty())
{
temp = lstack.top();
lstack.pop();
switch(temp)
{
case 10:printf("A");
break;
case 11:printf("B");
break;
case 12:printf("C");
break;
case 13:printf("D");
break;
case 14:printf("E");
break;
case 15:printf("F");
break;
default:
printf("%d", temp);
}
}
return 0;
}
第二章 链表和线性表
-
慕课
- 注意给的字母是指针还是数据。。。
- 双向链表的优点是很方便的插入和删除数据。
顺序表算法
创建空顺序表、输入数据、(判空判满不单独写函数了)、插入某个位置前、插入某个位置后、查找元素某个元素的位置、删除某个位置元素、删除某个元素以及之后的连续几个元素、删除表中所有值为x的元素、删除某个位置到某个位置的元素。(这里的位置我按照从1开始)
🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰🔰
打印函数和主函数:
void print(Seqlist list)
{
for (int i = 0; i < list->n; i++)
{
printf("%d ", list->elem[i]);
}
printf("\n");
}
int main()
{
int max,location,location2;
Datatype data;
int len;
printf("Please input the seq max\n");
scanf("%d", &max);
Seqlist list = CreatNullList(max);
Input_data(list);//-1为标志
print(list);
//printf("input the location and data you want to insert\n");
//scanf("%d %d", &location,&data);
//Insert_belocation(list, location, data);//在location前插入。
//print(list);
//Insert_aflocation(list, location, data);//在location后插入。
//print(list);
//printf("input the data that you want to find\n");
//scanf("%d", &data);
//Search(list, data);
//printf("input the location you want to delete\n");
//scanf("%d", &location);
//Delete_1(list, location);
//print(list);
//printf("input the data and len you want to delete\n");
//scanf("%d %d", &data, &len);
//Delete_2(list,data,len);
//print(list);
//printf("input the data you want to delete\n");
//scanf("%d", &data);
//Delete_3(list, data);
//print(list);
printf("input the location and location you want to delete\n");
scanf("%d %d", &location, &location2);
Delete_4(list, location, location2);
print(list);
return 0;
}
输入数据(以-1截止)
void Input_data(Seqlist list)
{
Datatype temp;
printf("please input data\n");
scanf("%d", &temp);
for (int i = 0; i < list->max; i++)
{
if (temp == -1) break;//-1为结束标志
list->elem[i] = temp;
list->n++;
scanf("%d", &temp);
}
}
插在某个位置前:
void Insert_belocation(Seqlist list,int location,Datatype data )//插在某个位置前
{
int i = 0;
if (list->n >= list->max)
{
printf("NO!I am full!!\n");
return;
}
for (i = list->n; i >= location; i--)//注意用减的时候的判断得是大于啊!
{
list->elem[i] = list->elem[i-1];//i-1的位置腾出来
}
list->elem[i] = data;//最后的循环结束,再i--,刚好是腾出来的位置。
list->n++;
}
/*数据:
20
1 2 3 4 5 6 -1
6 7
20
1 2 3 4 5 6 -1
5 8
20
1 2 3 4 5 6 -1
1 3
*/
插在某个位置后(其实就是比上一个对location的判断少一个等于)
void Insert_aflocation(Seqlist list, int location, Datatype data)//插在某个位置后
{
int i = 0;
if (list->n >= list->max)
{
printf("NO!I am full!!\n");
return;
}
for (i = list->n; i > location; i--)
{
list->elem[i] = list->elem[i - 1];
}
list->elem[i] = data;
list->n++;
}
/*数据:
20
1 2 3 4 5 6 -1
6 7
20
1 2 3 4 5 6 -1
5 8
20
1 2 3 4 5 6 -1
1 3
*/
寻找某个元素的位置
void Search(Seqlist list, Datatype data)
{
int i = 0;
int flag = 0;//表明有没有查到
for (i = 0; i < list->n; i++)
{
if (data == list->elem[i])
{
printf("the location is %d\n", i+1);
flag = 1;
}
}
if (flag == 0)printf("NO,it is not exist\n");
}
/*
20
1 2 2 3 4 5 6 7 -1
2
20
1 2 2 3 4 5 6 7 -1
8
*/
删除某个位置元素(没检测是否存在这个位置)
void Delete_1(Seqlist list, int location)
{
int i = 0;
if (location == list->n - 1)
list->n--;
else
{
for (i = location-1; i < list->n-1; i++)
{
list->elem[i] = list->elem[i+1];
}
list->n--;
}
}
/*
20
1 2 3 4 5 6 -1
6
20
1 2 3 4 5 6 -1
1
20
1 2 3 4 5 6 -1
3
*/
删除某个元素以及之后的连续几个元素
void Delete_2(Seqlist list, Datatype data, int len)
{
int i;
int del_len = len + 1;
for (i = 0; i < list->n; i++)
{
if (list->elem[i] == data) break;
}
if (i + len >= list->n - 1)//也就是从i包括i,以后的元素都被删了
{
list->n = i;
}
else
{
for (int j = i;j+del_len<list->n; j++)
{
list->elem[j] = list->elem[j + del_len];
}
list->n -= del_len;
}
}
/*
20
1 2 3 4 5 6 7 -1
3 2
20
1 2 3 4 5 6 7 -1
3 9
20
1 2 3 4 5 6 7 -1
7 0
*/
删除表中所有值为x的元素
注意:这里出现过错误,经调试才发现。
void Delete_3(Seqlist list, Datatype data)//搜索与单个删除的结合
{
void print(Seqlist list);
int i = 0;
int flag = 0;//表明有没有查到
for (i = 0; i < list->n; i++)
{
if (data == list->elem[i])
{
Delete_1(list, i+1);
i--;//都往前挪了,i不可以加!!!!注意,这里出现过错误,经调试才发觉。
//print(list);
flag = 1;
}
}
if (flag == 0)printf("NO,it is not exist\n");
}
/*
20
1 2 2 2 2 3 2 2 4 -1
2
20
1 2 2 2 2 3 4 -1
5
*/
删除某个位置到某个位置的元素。
void Delete_4(Seqlist list, int location1, int location2)
{
int len = location2 - location1+1;
if (location2 >= list->n)//从location1开始全删了
{
list->n = location1-1;//这里注意减1才是正确的数量,之前那个删除某个元素不用是因为找的是以0为开始的位置,没有改成为1的。
}
else
{
for (int i = location1 - 1; i + len < list->n; i++)
{
list->elem[i] = list->elem[i + len];
}
list->n -= len;
}
}
/*
20
1 2 3 4 5 6 7 -1
3 9
20
1 2 3 4 5 6 7 -1
2 6
*/
链表算法
创建空顺序表、输入数据、(判空判满不单独写函数了)、插入某个元素前、插入某个元素后、删除某个位置元素、删除某个元素以及之后的连续几个元素、删除表中所有值为x的元素、删除某个位置到某个位置的元素。(这里的位置我按照从1开始)
打印函数和主函数:
输入数据(以-1为截止)(尾插法)(注意容易忘记的地方)
void Input(PNode head)//尾插法
{
PNode q = head;
int data;
scanf("%d", &data);
while (data != -1)
{
PNode p = (PNode)malloc(sizeof(struct Node));
p->data = data;
p->next = NULL;
q->next = p;
q = p;
scanf("%d", &data);//别忘了,上次的顺序表就也忘了一次加这个!
}
}
插入到某个元素前
void Insert_pr(PNode head, Datatype data1, Datatype data2)//1判断,2是插入的元素,这个是插在1前面。
{
PNode p = head->next;
PNode q = head;
PNode temp = NULL;
temp = (PNode)malloc(sizeof(struct Node));
temp->data = data2;
temp->next = NULL;
while (p != NULL)
{
if (p->data == data1) break;//注意,不能放在while的判断里,否则NULL是会触发空指针访问
q = p;
p = p->next;
}
if (p!=NULL)
{
q->next = temp;
temp->next = p;
return;
}
}
插入到某个元素后(跟上一个很像,删删改改就好)
void Insert_af(PNode head, Datatype data1, Datatype data2)//1判断,2是插入的元素,这个是插在1后面。
{
PNode p = head->next;
PNode temp = NULL;
temp = (PNode)malloc(sizeof(struct Node));
temp->data = data2;
temp->next = NULL;
while (p != NULL)
{
if (p->data == data1) break;//注意,不能放在while的判断里,否则NULL是会触发空指针访问
p = p->next;
}
if (p != NULL)
{
temp->next = p->next;
p->next = temp;
return;
}
}
删除某个位置元素(没考虑不存在)
void Del_lin(PNode head, int location)
{
PNode p = head;
PNode q = p;
while (location > 0)
{
q = p;
p = p->next;
location--;
}
q->next = p->next;
free(p);
}
删除某个元素以及之后的连续几个元素
void Del_c_l(PNode head, Datatype charge, int len)
{
PNode p = head->next;
PNode q = head;
len += 1;//共删除len+chage data=len+1个元素
while (p != NULL)
{
if (p->data == charge) break;
q = p;
p = p->next;
}
while (p != NULL&&len>0)
{
q->next = p->next;
free(p);
if (q->next != NULL)
{
p = q->next;
len--;
}
else
{
q->next = NULL;
break;
}
}
}
删除表中所有值为x的元素
void Del_c_a(PNode head, Datatype data)
{
PNode p = head->next;
PNode q = head;
while (p != NULL)
{
if (p->data == data)
{
q->next = p->next;
free(p);
p = q->next;
}
else
{
q = p;
p = p->next;
}
}
}
删除某个位置到某个位置的元素
void Del_location_2(PNode head, int location1, int location2)
{
PNode p, q;
p = head;
q = head;
while (location1 > 0&&p!=NULL)
{
q = p;
p = p->next;
location1--;
location2--;
}
location2++;//location1位置上的还需要一次。其实本质是在用删除的次数来循环,del_len=locaton2-location1+1
while (location2 > 0&&p!=NULL)
{
q->next = p->next;
free(p);
p = q->next;
location2--;
}
}
len--;
}
else
{
q->next = NULL;
break;
}
}
}
###### 删除表中所有值为x的元素
```c
void Del_c_a(PNode head, Datatype data)
{
PNode p = head->next;
PNode q = head;
while (p != NULL)
{
if (p->data == data)
{
q->next = p->next;
free(p);
p = q->next;
}
else
{
q = p;
p = p->next;
}
}
}
删除某个位置到某个位置的元素
void Del_location_2(PNode head, int location1, int location2)
{
PNode p, q;
p = head;
q = head;
while (location1 > 0&&p!=NULL)
{
q = p;
p = p->next;
location1--;
location2--;
}
location2++;//location1位置上的还需要一次。其实本质是在用删除的次数来循环,del_len=locaton2-location1+1
while (location2 > 0&&p!=NULL)
{
q->next = p->next;
free(p);
p = q->next;
location2--;
}
}