参考:《啊哈算法》
嗯,抄代码的意义在于你能不能抄正确!
嗯,我又开始了新的学习,任务没有完成哪里还有时间吃饭?不逼逼自己不知道自己的潜力究竟有多大!
本章的基本数据结构都是使用的顺序表实现的!不管那么多,动手才是硬道理,先理解原理才是硬道理。虽然上学期已经学过这个了,但是,。,。,。坚持做自己不想做的,得到别人得不到的。
1,队列。(和标题顺序不符呀)对列就是先进先出。(FIFO)
问题:序列631758924,删除对头,次对头放到队尾,重复操作直到队为空,求删除数字序列(即QQ号)
数组模拟,一个head,一个tail.head++删除头,tail++尾部插入
成功解密QQ号
(注意:判断队空的条件是队头等于队尾。技巧:通常把tail设到队尾的下一位,方便直接添加,比较直观。否则,还要先tail++一次
#include<iostream>
using namespace std;
const int N=100;
int main()
{
int a[N]={6,3,1,7,5,8,9,2,4},head,tail;
head=0;
tail=9;
//while(head<tail)
while(a[head]){
cout<<a[head]<<ends;//输出队头
head++;//前进到下一位
a[tail]=a[head];//送到对尾部
head++;//后移
tail++;//后移
}
cout<<endl;
return 0;
}
结构体封装的队列(队列三个基本元素,数据内容,队首,队尾)
#include <iostream>
using namespace std;
const int N=100;
typedef struct Que {
char data[N];
int head;
int tail;
};
int main() {
cout<<"Please enter the QQ :"<<endl;
Que q;
char c;
int i=0;
while(cin>>c) {
q.data[i++]=c;
}
int n=i;//i就是总数据数
q.head=0;
q.tail=n;
while(q.head<q.tail) {
cout<<q.data[q.head]<<ends;
q.head++;
q.data[q.tail]=q.data[q.head];
q.head++;
q.tail++;
}
cout<<endl;
return 0;
}
嗯,再来一发,STL封装的队列
进队:push()
出队:pop()
队首:.front()
队尾:.back()
#include<iostream>
#include <queue>
using namespace std;
int main()
{
queue<char> QQ;
cout<<"Please enter the QQ:"<<endl;
char c;
while(cin>>c){
QQ.push(c);
}
while(!QQ.empty()){
cout<<QQ.front()<<ends;
QQ.pop();
QQ.push(QQ.front());
QQ.pop();
}
return 0;
}
2,栈,栈规定只能在一端进行操作,因此栈为后进先出,(FILO)
顺序表表示的话,就是一个栈顶top,top++,top–进出栈
问题:判断字符串是不是回文串
#include<iostream>
using namespace std;
const int N=10;
char str[N];
int main() {
char c;
int i=0;
while(cin>>c) {
str[i++]=c;
}
int n=i;
int mid=n/2-1;
int top=0;
for(int i=0; i<=mid; i++) {
str[top++]=str[i];
}
top=top-1;
int next;
if(n%2==0) {
next=mid+1;
} else {
next=mid+2;
}
int flag=1;
for(int i=next; i<n; i++) {
if(str[i]!=str[top--]) {
flag=0;
break;
}
}
if(flag){
cout<<"YES"<<endl;
}
else {
cout<<"NO"<<endl;
}
return 0;
}
(发现个问题,自己看了书,再自己弄一遍的过程中,分析的时候简直是移步到位,越来越多的技巧,比如使用寄存器,计数器,怎么往逻辑外传逻辑内得到的参数值,再比如这里找中点和另一半的起始位置简直了)
STL stack的用法,push,pop,.top()
判断回文串嘛,怎么需要用栈尼,栈用在括号匹配才是硬道理,没学之前处理括号匹配实在是繁杂。
下面是简单的判断回文串。(以前看舍友的代码,有些知识,真的是会过目不忘)
#include<iostream>
#include <stack>
using namespace std;
#define N 100
char str[N];
int main() {
char c;
int i=0;
while(cin>>c) {
str[i++]=c;
}
int n=i;
bool flag=true;
for(int i=0,j=n-1;i<=j; i++,j--) {
if(str[i]!=str[j]) {
flag=false ;
break;
}
}
if(flag) {
cout<<"YES"<<endl;
} else {
cout<<"NO"<<endl;
}
return 0;
}
3,链表。之前看过谭叔的书。最后一章就是讲得链表,当时也是抄了几遍代码。思维有点混乱。
提到链表就不得不说起指针,指针就是用来存放内存地址的,常用*号表示。
提到链表就不得不说增删改查,于是用于增加的动态申请就出来了。
下面是对*在C/C++中用途的总结:
- *用作乘法符号。
- *声明一个指针。eg:int *p
*间接运算符(解引用)
指针的范例
#include<cstdio>
#include <cstdlib>
int main()
{
int *p;
p=(int*)malloc(sizeof(int));
*p=10;
printf("%d\n",*p);
return 0;
}
(mallooc函数在stdlib里面,free释放)
嗯,简单来说使用指针的步骤有两步,第一是定义指针变量;第二就是给指针变量填充内容(赋值),值可以是地址&a,也可是*p=a的形式
下面的代码与上一段程序实现相同的内容:
#include <cstdio>
#include <cstdlib>
int main()
{
int *p;
int a;
scanf("%d",&a);
p=&a;
printf("%d\n",*p);
return 0;
}
当然C++中是使用new 来动态动态申请空间,delete进行释放。
#include <iostream>
using namespace std;
int main()
{
int *p;
p=new int ;
*p=10;
cout<<*p<<endl;
delete p;
return 0;
}
下面的程序是一定错误的,禁忌,因为没有申请分配空间,仅仅是定义了一个变量
#include <iostream>
using namespace std;
int main() {
int *p;
*p=10;
cout<<*p<<endl;
return 0;
}
简单的建立链表
#include <iostream>
#include <cstdlib>
using namespace std;
typedef struct Node { //不要混淆在这里写成*Node,节点类型一般不设为指针
int data;
struct Node *next;//自引用,定义了结点的内容。
};
int main() {
int T;
Node *p,*q,*head;
head=NULL;
cin>>T;
while(T--) {
int a;
cin>>a;
p=(Node*)malloc(sizeof(Node));
p->data=a;
p->next=NULL;
if(head==NULL) {//这里以前一直不是很懂,终于明白了
head=p;
} else {
q->next=p;
}
q=p;
}
p=head;
while(p!=NULL) {
cout<<p->data<<ends;
p=p->next;
}
cout<<endl;
}
链表添加和删除(排除在第一位添加和删除的情况)
#include <iostream>
#include <cstdlib>
using namespace std;
typedef struct Node { //不要混淆在这里写成*Node,节点类型一般不设为指针
int data;
struct Node *next;//自引用,定义了结点的内容。
};
int main() {
int T;
Node *p,*q,*head;
head=NULL;
cout<<"Please enter the amount of list node:"<<endl;
cin>>T;
cout<<"Please enter the list :(ctrl+z to end)"<<endl;
while(T--) {
int a;
cin>>a;
p=(Node*)malloc(sizeof(Node));
p->data=a;
p->next=NULL;
if(head==NULL) {//这里以前一直不是很懂,终于明白了
head=p;
} else {
q->next=p;
}
q=p;
}
p=head;
cout<<"You have created the list:"<<endl;
while(p!=NULL) {
cout<<p->data<<ends;
p=p->next;
}
//添加数据
cout<<"\nPlease enter the number you want to add"<<endl;
int b;
cin>>b;
p=(Node*)malloc(sizeof(Node));
p->data=b;
p->next=NULL;
Node *it;
it=head;
while(it!=NULL) {
if(it->next!=NULL&&it->next->data>b) {//妙,先看看下一项,不过这里好像健壮性不强,要是在第一个位置就要插入怎么办?
p->next=it->next;
it->next=p;
break;//插入结束
}
it=it->next;
}
cout<<"The new list:"<<endl;
p=head;
while(p!=NULL) {
cout<<p->data<<ends;
p=p->next;
}
cout<<endl;
//删除数据
cout<<"Please enter the number which you want to delete :"<<endl;
cin>>b;
it=head;
while(it!=NULL) {
if(it->next!=NULL&&it->next->data==b) {
it->next=it->next->next;
break;
}
it=it->next;
}
cout<<"The new list:"<<endl;
p=head;
while(p!=NULL) {
cout<<p->data<<ends;
p=p->next;
}
cout<<endl;
return 0;
}
执行:
4,嗯,最后的模拟链表简直是第一次看见,没有多大作用,用一个数组记录数据,再用一个数组记录数据数组右边的数据存在哪一个位置。