markdown:
#include<iostream>
#include<string>
using namespace std;
bool check(string s)
{
for(int i=0;i<s.size();i++)
if(s[i]=='('||s[i]==')')
return true;
return false;
}
string itoa(float x)
{
string s;
int d=0,dem=0,a;
if(x==0) s.insert(0,"0");
if(x<0)
{
d=1;
x=-x;
}
while(float(x)-long(x)!=0)
{
dem++;
x*=10;
}
long z=long(x);
for(int i=0;i<dem;i++)
{
a=z%10;
z/=10;
switch(a)
{
case 0:s.insert(0,"0");break;
case 1:s.insert(0,"1");break;
case 2:s.insert(0,"2");break;
case 3:s.insert(0,"3");break;
case 4:s.insert(0,"4");break;
case 5:s.insert(0,"5");break;
case 6:s.insert(0,"6");break;
case 7:s.insert(0,"7");break;
case 8:s.insert(0,"8");break;
case 9:s.insert(0,"9");break;
}
}
if(dem>0)s.insert(0,".");
if(z==0) s.insert(0,"0");
while(z>0)
{
a=z%10;
z/=10;
switch(a)
{
case 0:s.insert(0,"0");break;
case 1:s.insert(0,"1");break;
case 2:s.insert(0,"2");break;
case 3:s.insert(0,"3");break;
case 4:s.insert(0,"4");break;
case 5:s.insert(0,"5");break;
case 6:s.insert(0,"6");break;
case 7:s.insert(0,"7");break;
case 8:s.insert(0,"8");break;
case 9:s.insert(0,"9");break;
}
}
if(d==1) s.insert(0,"-");
else s.insert(0,"+");
return s;
}
float lay1(string s)
{
long d=1;
float x=0;
for(int i=s.size()-1;i>=0;i--)
{
if(s[i]=='-' || s[i]=='+' || s[i]=='*' || s[i]=='/' || s[i]=='(' || s[i]==')')
{
if(s[i]=='-') x=-x;
break;
}
else if(s[i]=='.')
{
x/=d;
d=1;
}
else
{
switch(s[i])
{
case '0':break;
case '1':x+=d;break;
case '2':x+=2*d;break;
case '3':x+=3*d;break;
case '4':x+=4*d;break;
case '5':x+=5*d;break;
case '6':x+=6*d;break;
case '7':x+=7*d;break;
case '8':x+=8*d;break;
case '9':x+=9*d;break;
}
d*=10;
}
}
return x;
}
float lay2(string s)
{
long j=0,k=0,i;
float d;
float x=0;
if(s[0]=='+' || s[0]=='-') j=1;
for(i=j;i<s.size();i++)
{
if(s[i]>='0' && s[i]<='9')
{
switch(s[i])
{
case '0':x=x*10+0;break;
case '1':x=x*10+1;break;
case '2':x=x*10+2;break;
case '3':x=x*10+3;break;
case '4':x=x*10+4;break;
case '5':x=x*10+5;break;
case '6':x=x*10+6;break;
case '7':x=x*10+7;break;
case '8':x=x*10+8;break;
case '9':x=x*10+9;break;
}
}
else break;
}
if(i<s.size() && s[i]=='.')
{
d=10;
for(j=i+1;j<s.size();j++)
{
if(s[j]>='0' && s[j]<='9')
{
switch(s[j])
{
case '0':x+=0/d;break;
case '1':x+=1/d;break;
case '2':x+=2/d;break;
case '3':x+=3/d;break;
case '4':x+=4/d;break;
case '5':x+=5/d;break;
case '6':x+=6/d;break;
case '7':x+=7/d;break;
case '8':x+=8/d;break;
case '9':x+=9/d;break;
}
d*=10;
}
else break;
}
}
if(s[0]=='-') x=-x;
return x;
}
void xuly(string &s)
{
if(s[s.size()-1]=='+'||s[s.size()-1]=='-')
{
s.push_back('0');
}
if(s[s.size()-1]=='*'||s[s.size()-1]=='/')
{
bool p=false;
for(int i=s.size()-2;i>=0;i--)
if(s[i]=='+'||s[i]=='-')
{
p=true;
i++;
s.replace(i,s.size()-i,"0");
}
if(p==false)
{
s.erase(0,s.size());
s.insert(0,"0");
}
}
for(int i=0;i<s.size()-1;i++)
if(s[i]=='+' && s[i+1]=='+')
{
s.erase(i,1);
}
else if(s[i]=='+' && s[i+1]=='-')
{
s.erase(i,1);
}
else if(s[i]=='-' && s[i+1]=='+')
{
s.erase(i+1,1);
}
else if(s[i]=='-' && s[i+1]=='-')
{
s.erase(i,2);
s.insert(i,"+");
}
}
float tinh(string s)
{
xuly(s);
int p1,p2;
string a,c;
float x,y,t=0,p;
while(check(s))
{
p2=s.find(")");
if(p2>=0)
{
xuly(s);
p1=s.rfind("(",p2);
a=s.substr(p1+1,p2-p1-1);
p=tinh(a);
c=itoa(p);
s.replace(p1,p2-p1+1,c);
xuly(s);
}
}
loop:;
for(p=0;p<s.size();p++)
if(s[p]=='*' || s[p]=='/') break;
if(p!=s.size())
{
xuly(s);
a=s.substr(0,p);
c=s.substr(p+1,s.size()-p-1);
x=lay1(a);
y=lay2(c);
if(s[p]=='*') t=x*y;
else t=x/y;
for(p1=p-1;p1>=0;p1--)
if(s[p1]=='+' || s[p1]=='-'|| s[p1]=='*'|| s[p1]=='/'|| s[p1]=='('|| s[p1]==')') break;
if(p1==-1) p1++;
else if(s[p1]=='*' || s[p1]=='/') p1++;
for(p2=p+2;p2<s.size();p2++)
if(s[p2]=='+' || s[p2]=='-'|| s[p2]=='*'|| s[p2]=='/'|| s[p2]=='('|| s[p2]==')') break;
p2--;
a=itoa(t);
s.replace(p1,p2-p1+1,a);
xuly(s);
goto loop;
}
//dau +-
else
{
int k;
do{
k=0;
for(p=1;p<s.size();p++)
if(s[p]=='+' || s[p]=='-') break;
if(p<s.size())
{
xuly(s);
a=s.substr(0,p);
c=s.substr(p+1,s.size()-p-1);
x=lay1(a);
y=lay2(c);
if(s[p]=='+') t=x+y;
else t=x-y;
a=itoa(t);
for(p2=p+1;p2<s.size();p2++)
if(s[p2]=='+' || s[p2]=='-') break;
p2--;
s.replace(0,p2+1,a);
xuly(s);
k=1;
}
}while(k);
}
t=lay1(s);
return t;
}
void main()
{
string s;
getline(cin,s);
cout<<s<<" = ";
cout<<tinh(s)<<endl;
system("pause");
}
# Thuật toán trong lập trình Công nghệ thông tin
Tổng hợp các thuật toán lập trình mới nhất trong ngành công nghệ thông tin, các bài viết về ngôn ngữ lập trình C, Java, HTML, php...
###
[lập trình c++ tính giá trị biểu thức toán học](http://www.thuattoan.net/2015/05/lap-trinh-c-tinh-gia-tri-bieu-thuc-toan.html)
viết chương trình tính giá trị của 1 biểu thức toán học thông thường với số thực, số nguyên đều được và các phép toán cộng + trừ - nhân * chia / và dấu ngoặc. thuật toán này được thiết kế code c++ bởi Trần Khánh Toàn, cái hay của bài này là tính được cả số thực, các biểu thức nếu máy tính fx-500ms tính được thì nó tính được, riêng phần báo lỗi thì nó không có, nhập biểu thức sai cú pháp thì nó chạy sai hoặc hệ thống báo không chạy được chương trình này, không gì là hoàn hảo cả nên t sẽ cố gắng cải tiến và update lên đây để mọi người học hỏi kinh nghiệm.
###
[Lập trình game trên mobile - Android - iOS - WinPhone](http://www.thuattoan.net/2015/05/lap-trinh-game-tren-mobile-android-ios.html)
Dành cho các bạn đam mê lập trình game và muốn theo nghề lập trình game.
Yêu cầu cần có kiến thức cơ bản về lập trình, cơ bản Lập trình hướng đối tượng.
Ngôn ngữ sử dụng để viết game:
Phát triển Game sử dụng Engine để build đa nền tản( Sử dụn 1 ngôn ngữ để viết code ở 1 project core sau đó build qua các nền tảng khác ( Android, iOS, Winphone, Win8, ...))
Xem chi tiết các nội dung cần tìm hiểu:
Sử dụng Engine để làm game đa nền tảng
Engine Cocos2d-x
Yêu cầu cần có kiến thức cơ bản về lập trình, cơ bản Lập trình hướng đối tượng.
Ngôn ngữ sử dụng để viết game:
- Android: Java (sủ dụng Engine Libgdx hoặc AndEngine )
- iOS: Swift (sủ dụng Engine SpriteKit)
- Đa nền tảng ( Android, iOS, Winphone, Win8, ...): C/C++ ( sử dụng Engine Cocos2d-x )
Phát triển Game sử dụng Engine để build đa nền tản( Sử dụn 1 ngôn ngữ để viết code ở 1 project core sau đó build qua các nền tảng khác ( Android, iOS, Winphone, Win8, ...))
![]()
**CHƯƠNG TRÌNH LẬP TRÌNH GAME TRÊN ANDROID**
1. Giới thiệu về OpenGL trên Android, kỹ thuật đồ họa 2D,3D trên Android (2 buổi)
2. Mô hình kiến trúc Lập trình Game (1 buổi)
3. Các ý tưởng lập trình Game (1 buổi)
4. Giới thiệu các thư viện sử dụng lập trình game trên Android (2 buổi)
5. Làm việc với AndEngine để lập trình game (4 buổi)
6. Nguyên tắc sử dụng Engine, Scene trong việc lập trình Game (2 buổi)
7. Các đối tượng trên Game, Sprite, AnimatedSprite, Layer,Particle, Shape, Text (3 buổi)
8. Audio trên Game (1 buổi)
9. Nguyên tắc va chạm, chuyển động khi lập trình game (2 buổi)
10. Sử lý hình ảnh trên Game (2 buổi)
11. Viết các game cơ bản (3 buổi)
**CHƯƠNG TRÌNH LẬP TRÌNH GAME ĐA NỀN TẢN ( ANDROID, IOS, WINPHONE, WIN 8 ) SỬ DỤNG ENGINE COCOS2D-X**
![]()
1. Ôn tập kiến thức C/C++ và lập trình hướng đối tượng (2 buổi)
2. Mô hình kiến trúc Lập trình Game (1 buổi)
3. Các ý tưởng lập trình Game (1 buổi)
4. Giới thiệu Engine Cocos2d-x (2 buổi)
5. Làm việc với Engine Cocos2d-x để lập trình game (4 buổi)
6. Nguyên tắc sử dụng Engine, Scene trong việc lập trình Game (2 buổi)
7. Các đối tượng trên Game, Sprite, AnimatedSprite, Layer,Particle (3 buổi)
8. Audio trên Game (1 buổi)
9. Nguyên tắc va chạm, chuyển động khi lập trình game (2 buổi)
10. Sử lý hình ảnh trên Game (2 buổi)
11. Viết các game cơ bản (3 buổi)
BẠN NÀO CÓ NHU CẦU TÌM HIỂU LÀM GAME CÓ THỂ COMMENT DƯỚI BÀI VIẾT NHÉ <3 AD page
Các bạn comment ở dưới bài viết để trao đổi nhé :D
BẠN NÀO CÓ NHU CẦU TÌM HIỂU LÀM GAME CÓ THỂ COMMENT DƯỚI BÀI VIẾT NHÉ <3 AD page
[Học Lập Trình](https://www.facebook.com/hoclaptrinh.it?_rdr)
Các bạn comment ở dưới bài viết để trao đổi nhé :D
###
[Internet of Things](http://www.thuattoan.net/2015/05/internet-of-things.html)
1. Khái niệm Internet of Things
Internet of Things (IoT) là một kịch bản của thế giới, khi mà mỗi đồ vật, mỗi đồ vật, con người được cung cấp một định danh của riêng mình, và tất cả có khả năng truyền tải, trao đổi thông tin, dữ liệu qua một mạng duy nhất mà không cần đến sự tương tác trực tiếp giữa người với người, hay người với máy tính. IoT đã phát triển từ sự hội tụ của công nghệ không dây, công nghệ vi cơ điện tử và Internet.
2. Xu hướng của thế giới Internet of Things
Như vậy có thể tạm hiểu, Internet of Things là khi tất cả mọi thứ đều được kết nối với nhau qua mạng Internet, người dùng (chủ) có thể kiểm soát mọi đồ vật của mình qua mạng mà chỉ bằng một thiết bị thông minh, chẳng hạn như smartphone, tablet, PC hay thậm chí chỉ bằng một chiếc smartwatch nhỏ bé trên tay.
![]()
* Các giao thức giao tiếp không dây trong thế giới IoT được thiết kế để thỏa mãn các yêu cầu cơ bản:
Tiêu tốn ít năng lượng cho việc thu/phát sóng,
Tiêu tốn ít băng thông (để giảm gánh nặng cho router wireless và hệ thống mạng), hoạt động trong mạng mắt lưới…
*
**Một số thiết bị sẽ giao tiếp qua:**
- Wi-fi
- Bluetooth,
- NFC
- Nhưng đa phần sẽ tận dụng các kết nối sử dụng dải tần của mạng không dây.
3. Ứng dụng của Internet of Things
- Dùng iPhone mở khóa MacBook:
Knock, được phát triển bởi Knock Software Inc và đang bán trên Apple Store với giá 3.99 USD.
Công dụng của Knock là giúp bạn dùng iPhone để unlock (mở khóa) MacBook bằng cách cầm iPhone gõ hai cái lên đâu đó.
- Nhà thông minh (Smart Home)
Ứng dụng BLE để điều khiển máy lạnh, TV, đèn, máy giặt… nói chung là mọi thiết bị trong ngôi nhà của bạn. Biến chiếc mobile của bạn thành chiếc remote đa năng, điều khiển đủ mọi thứ trong nhà và thậm chí không cần điều khiển, đèn vẫn có thể tự tắt.
ĐTDĐ của các bạn sẽ cần cài đặt một phần mềm để làm trung tâm điều khiển,
Cứ mỗi thiết bị cần điều khiển sẽ gắn một thiết bị ngoại vi
Cài đặt lệnh cho từng thiết bị ngoại vi ấy như là bấm lệnh gì thì thiết bị nào sẽ thực thi điều gì .
Không thì toàn bộ thiết bị điện trong nhà sẽ tắt hết, trừ tủ lạnh, chẳng hạn.
7. Hướng dẫn tìm hiểu Internet of things
7. Hướng dẫn tìm hiểu Internet of things
-
[http://www.intel.com/content/www/us/en/internet-of-things/overview.html]
-
[http://www.arduino.cc/] - [http://www.visualmicro.com/]
###
[phần mềm split and join file part,001,002](http://www.thuattoan.net/2015/04/phan-mem-split-and-join-file-part001002.html)
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
#include<Windows.h>
void layten(char *duongdan,char *ten)
{
int d=0;
for(int i=strlen(duongdan)-1;i>=0;i--)
if(duongdan[i]!='/' && duongdan[i]!='\\') ten[d++]=duongdan[i];
else break;
ten[d]='\0';
for(int i=0;i<strlen(ten)/2;i++)
{
char c=ten[i];
ten[i]=ten[strlen(ten)-1-i];
ten[strlen(ten)-1-i]=c;
}
}
void bang(char *a,char *b)
{
for(int i=0;i<strlen(b);i++) a[i]=b[i];
a[strlen(b)-1]='\0';
}
int insertpass(char *duongdan,char *mk)
{
FILE *t=fopen(duongdan,"rb+");
FILE *f=fopen("logTKT.bin","wb+");
if(t==NULL || f==NULL) return 0;
fwrite(mk,8,1,f);
char s[2];
while(fread(s,1,1,t)) fwrite(s,1,1,f);
rewind(t);rewind(f);
while(fread(s,1,1,f)) fwrite(s,1,1,t);
fcloseall();
remove("logTKT.bin");
return 1;
}
int pass_ok(char *s)
{
int dem=0;
for(int i=0;i<strlen(s);i++)
if(s[i]>='0' && s[i]<='9') dem++;
if(dem!=strlen(s) || dem!=6) return 0;
s[6]=s[7]='#';
s[8]='\0';
return 1;
}
int split(char *duongdan,char *thumuc,int n)
{
char ten[100],duongdan2[100],a[10],*s=new char[2];
unsigned long dungluong,dem;
int i;
layten(duongdan,ten);
strcat(thumuc,"/");
strcat(thumuc,ten);
strcat(thumuc,".partt");
FILE *t=fopen(duongdan,"rb");
if(t==NULL)
{
printf("\nduong dan file khong hop le!");
return 0;
}
fseek(t,0,2);
dungluong=ftell(t)/n;
rewind(t);
for(i=1;i<n;i++)
{
bang(duongdan2,thumuc);
a[0]='\0';
itoa(i,a,10);
strcat(duongdan2,a);
FILE *f=fopen(duongdan2,"wb");
if(f==NULL)
{
printf("\nduong dan thu muc chua file ket qua khong hop le!");
return 0;
}
dem=0;
do{
fread(s,1,1,t);
fwrite(s,1,1,f);
dem+=1;
}while(dem!=dungluong);
fclose(f);
}
bang(duongdan2,thumuc);
a[0]='\0';
itoa(n,a,10);
strcat(duongdan2,a);
FILE *f=fopen(duongdan2,"wb");
if(f==NULL)
{
printf("\nduong dan thu muc chua file ket qua khong hop le!");
return 0;
}
while(fread(s,1,1,t)) fwrite(s,1,1,f);
fclose(f);
delete []s;
fclose(t);
return 1;
}
int join(char *duongdan,char *thumuc)
{
int i;
char ten[100],duongdanketqua[100],a[10],s[2],dd[100];
layten(duongdan,ten);
for(i=strlen(ten)-1;i>=0;i--)
if(ten[i]!='.') ten[i]='\0';
else break;
ten[i]='\0';
duongdanketqua[0]='\0';
strcat(duongdanketqua,thumuc);
if(strlen(duongdanketqua)>0)strcat(duongdanketqua,"/");
strcat(duongdanketqua,ten);
FILE *t=fopen(duongdanketqua,"wb");
if(t==NULL)
{
printf("\nduong dan thu muc chua file ket qua khong hop le!\n");
return 0;
}
for(i=strlen(duongdan)-1;i>=0;i--)
if(duongdan[i]>='0' && duongdan[i]<='9') duongdan[i]='\0';
else break;
i=1;
while(1)
{
a[0]='\0';
itoa(i++,a,10);
bang(dd,duongdan);
strcat(dd,"t");
strcat(dd,a);
FILE *f=fopen(dd,"rb");
if(i==1 && f==NULL)
{
printf("\nduong dan file khong hop le!");
return 0;
}
if(f==NULL) break;
while(fread(s,1,1,f)) fwrite(s,1,1,t);
fclose(f);
}
fclose(t);
return 1;
}
int split2(char *duongdan,char *thumuc,char *dl)
{
unsigned long dungluong=0,dem;
int i;
char a[100],ten[100],duongdan2[100],s[2];
layten(duongdan,ten);
if(strlen(thumuc)>0)strcat(thumuc,"/");
strcat(thumuc,ten);
strcat(thumuc,".partt");
for(i=0;i<strlen(dl);i++)
if(dl[i]>='0' && dl[i]<='9') a[i]=dl[i];
else break;
a[i]='\0';
dungluong+=atol(a);
if(dl[i]=='K') dungluong*=1024;
if(dl[i]=='M') dungluong*=1024*1024;
FILE *t=fopen(duongdan,"rb");
if(t==NULL)
{
printf("\nduong dan file khong hop le!");
return 0;
}
i=1;
while(!feof(t))
{
bang(duongdan2,thumuc);
a[0]='\0';
itoa(i++,a,10);
strcat(duongdan2,a);
FILE *f=fopen(duongdan2,"wb");
if(f==NULL)
{
printf("\nduong dan thu muc chua file ket qua khong hop le!");
return 0;
}
dem=0;
for(dem=1;dem<=dungluong;dem++)
if(fread(s,1,1,t)) fwrite(s,1,1,f);
else break;
fclose(f);
}
return 1;
}
int co_pass(char *duongdan,char *pass)
{
FILE *t=fopen(duongdan,"rb+");
if(t==NULL) return -1;
char s[10];
fread(s,8,1,t);
if(s[6]=='#' && s[7]=='#')
{
int i;
for(i=0;i<6;i++) pass[i]=s[i];
pass[i]='\0';
fclose(t);
return 1;
}
fclose(t);
return 0;
}
void xuly_pass(char *duongdan)
{
FILE *t=fopen(duongdan,"rb");
FILE *f=fopen("logTKT.bin","wb+");
char s[10];
fread(s,8,1,t);
while(fread(s,1,1,t)) fwrite(s,1,1,f);
rewind(f);fclose(t);
t=fopen(duongdan,"wb");
while(fread(s,1,1,f)) fwrite(s,1,1,t);
fcloseall();
remove("logTKT.bin");
}
void main()
{
char duongdan[100],thumuc[100],dungluong[100],pass[100];
int n,k=1,kt,kiemtrapass;
while(k!=0)
{
system("cls");
printf("\n\n________________MENU___________________\n");
printf("| 1. chia file thanh n part.(split1) |\n");
printf("| 2. chia file theo dung luong.(split2)|\n");
printf("| 3. gop file (join) |\n");
printf("| 0. Thoat. |\n");
printf("________________________________________\n");
scanf("%d",&k);
if(k==1)
{
kiemtrapass=0;
printf("\nnhap vao DUONG DAN FILE chua file can Split: ");fflush(stdin);gets(duongdan);
printf("\nnhap vao THU MUC chua file ket qua Split: ");fflush(stdin);gets(thumuc);
printf("\nnhap vao SO PART can Split: N=");scanf("%d",&n);
printf("\nDo you Set PassWord?? 1-yes; 0-no; : ");scanf("%d",&kt);
if(kt==1)
{
kiemtrapass=1;
int kc,kl;
do{
kc=0;
printf("\nnhap 6 chu so password: ");fflush(stdin);gets(pass);
kl=pass_ok(pass);
if(kl==0)
{
printf("\nnhap pass sai dinh dang! nhap lai!");
kc=1;
}
}while(kc==1);
printf("\ndang cai dat PassWord vao file! doi nhe! ...");
kc=insertpass(duongdan,pass);
if(kc==0)
{
printf("\nduong dan file khong hop le!");
goto ketthuc1;
}
}
printf("\nDANG XU LY! VUI LONG DOI! ...");
kt=split(duongdan,thumuc,n);
if(kiemtrapass==1)xuly_pass(duongdan);
if(kt==1) printf("\nOK - Da Xong!\n");
ketthuc1:;
system("pause");
}
else if(k==2)
{
kiemtrapass=0;
printf("\nnhap vao DUONG DAN FILE chua file can Split: ");fflush(stdin);gets(duongdan);
printf("\nnhap vao THU MUC chua file ket qua Split: ");fflush(stdin);gets(thumuc);
do{
kt=0;
printf("\nnhap vao DUNG LUONG 1 part can Split: dung luong =");fflush(stdin);gets(dungluong);
int dem=0;
for(int i=0;i<strlen(dungluong);i++)
if((dungluong[i]>='0' && dungluong[i]<='9') || dungluong[i]=='B' || dungluong[i]=='K' || dungluong[i]=='M')
dem++;
if(dem!=strlen(dungluong))
{
printf("\nkhong hop le!");
kt=1;
}
}while(kt);
printf("\nDo you Set PassWord?? 1-yes; 0-no; : ");scanf("%d",&kt);
if(kt==1)
{
kiemtrapass=1;
int kc,kl;
do{
kc=0;
printf("\nnhap 6 chu so password: ");fflush(stdin);gets(pass);
kl=pass_ok(pass);
if(kl==0)
{
printf("\nnhap pass sai dinh dang! nhap lai!");
kc=1;
}
}while(kc==1);
printf("\ndang cai dat PassWord vao file! doi nhe! ...");
kc=insertpass(duongdan,pass);
if(kc==0)
{
printf("\nduong dan file khong hop le!");
goto ketthuc2;
}
}
printf("\nDANG XU LY! VUI LONG DOI! ...");
kt=split2(duongdan,thumuc,dungluong);
if(kiemtrapass==1)xuly_pass(duongdan);
if(kt==1) printf("\nOK - Da Xong!\n");
ketthuc2:;
system("pause");
}
else if(k==3)
{
printf("\nnhap vao DUONG DAN FILE part1: ");fflush(stdin);gets(duongdan);
printf("\nnhap vao THU MUC chua file ket qua: ");fflush(stdin);gets(thumuc);
char lay_pass[100];
printf("\ndang xu ly! ...");
int mk=co_pass(duongdan,lay_pass);
if(mk==-1)
{
printf("\nduong dan file khong hop le!");
goto ketthuc3;
}
else if(mk==1)
{
char check_pass[100];
printf("\nnhap PASS de join file: ");fflush(stdin);gets(check_pass);
if(strcmp(lay_pass,check_pass)!=0)
{
printf("\nnhap pass sai!!!");
goto ketthuc3;
}
else xuly_pass(duongdan);
}
printf("\nDANG XU LY! VUI LONG DOI! ...");
kt=join(duongdan,thumuc);
if(kt==1) printf("\nOK - Da Xong!\n");
ketthuc3:;
system("pause");
}
else printf("\n\nTAM BIET!\n");
}
getch();
}
###
[danh sách liên kết kép](http://www.thuattoan.net/2015/04/danh-sach-lien-ket-kep.html)
Cấu Trúc Dữ Liệu
Cấu trúc dữ liệu 1 nút
typedef struct tagDnode
{ Data Info;
struct tagDnode *pPre;
struct tagDnode *pNext;
}DNode;
Cấu trúc List kép
Typedef struct tagDList
{ DNode *pHead;
DNode *pTail;
}DList;
void CreateDList(DList &l)
{
l.DHead=NULL;
l.DTail=NULL;
}
Tạo 1 Nút Có Thành Phần Dữ Liệu = X
DNode *CreateDNode(int x)
{ DNode *tam;
tam=new DNode;
if(tam==NULL)
{ printf("khong con du bo nho");
exit(1);
}
else
{ tam->Info=x;
tam->pNext=NULL;
tam->pPre=NULL;
return tam;
}
}
Cài Đặt Thêm 1 Nút Vào Đầu Danh Sách
void AddFirst(DList &l, DNode *tam)
{
if(l.pHead==NULL)//xau rong
{
l.pHead=tam;
l.pTail=l.pHead;
}
else
{
tam->pNext=l.pHead;
l.pHead->pPre=tam;
l.pHead=tam;
}
}
Cài Đặt Thêm 1 Nút Vào Cuối Danh Sách
void AddEnd(DList &l,DNode *tam)
{
if(l.pHead==NULL)
{
l.pHead=tam;
l.pTail=l.pHead;
}
else
{
tam->pPre=l.pTail;
l.pTail->pNext=tam;
tam=l.pTail;
}
}
Cài Đặt Thêm 1 Nút Vào Sau Nút Q
void AddLastQ(DList &l,DNode *tam, DNode *q)
{
DNode *p;
p=q->pNext;
if(q!=NULL)//them vao duoc
{
tam->pNext=p;
tam->pPre=q;
q->pNext=tam;
if(p!=NULL)
p->pPre=tam;
if(q==l.pTail) //them vao sau danh sach lien ket.
l.pTail=tam;
}
else
AddFirst(l,tam);
}
Cài Đặt Thêm 1 Nút Vào Trước Nút Q
void AddBeforeQ(DList &l,DNode *tam,DNode *q)
{ DNode *p;
p=q->pPre;
if(q!=NULL)
{
tam->pNext=q;
q->pPre=tam;
tam->pPre=p;
if(p!=NULL)
p->pNext=tam;
if(q==l.pHead)
l.pHead = tam;
}
else
AddEnd(l,tam);
}
Xoá Phần Tử Đầu Danh Sách
void DeleteFirst(DList &l)
{
DNode *p;
if(l.pHead!=NULL)
{
p=l.pHead;
l.pHead=l.pHead->pNext;
l.pHead->pPre=NULL;
delete p;
if(l.pHead==NULL)
l.pTail=NULL;
}
}
Xoá 1 Phần Tử Cuối Danh Sách
void DeleteEnd(DList &l )
{
DNode *p;
if(l.pHead!=NULL) //tuc xau co hon mot phan tu
{
p=l.pTail;
l.pTail=l.pTail->Pre;
l.pTail->pNext=NULL;
delete p;
if(l.pTail==NULL)
l.pHead=NULL;
}
}
Hủy 1 Nút Sau Nút Q
void DeleteLastQ(DList &l,DNode *q)
{
DNode *p;//luu node dung sau node q
if(q!=NULL)
{
p=q->pNext;
if(p!=NULL)
{
q->pNext=p->pNext;
if(p==l.pTail)//xoa dung nu't cuoi
l.pTail=q;
else //Nut xoa khong phai nut cuoi
p->pNext->pPre=q;
delete p;
}
}
else
DeleteFirst(l);
}
Huỷ 1 Nút Đứng Trước Nút Q
void DeleteBeforeQ(DList &l,DNode *q)
{
DNode *p;
if(q!=NULL) //tuc ton tai node q
{
p=q->pPre;
if(p!=NULL)
{
q->pPre=p->pPre;
if(p==l.pHead)//p la Node dau cua danh sach
l.pHead=q;
else //p khong phai la node dau
p->pPre->pNext=q;
delete p;
}
}
else
DeleteEnd(l);
}
Xoá 1 Phần Tử Có Khoá = X
int DeleteX(DList &l,int x)
{
DNode *p;
DNode *q;
q=NULL;
p=l.pHead;
while(p!=NULL)
{
if(p->Info==x)
break;
q=p;//q la Node co truong Info = x
p=p->pNext;
}
if(q==NULL) return 0;//khong tim thay Node nao co truong Info =x
if(q!=NULL)
DeleteLastQ(l,q);
else
DeleteFirst(l);
return 1;
}
Sắp Xếp
void DoiChoTrucTiep(DList &l)
{ DNode *p,*q;
p=l.pHead;
while(p!=l.pTail)
{
q=p->pNext;
while(q!=NULL)
{
if(p->Info>q->Info)
HV(p,q);
q=q->pNext;
}
p=p->pNext;
}}
###
[danh sách liên kết đơn](http://www.thuattoan.net/2015/04/danh-sach-lien-ket-on.html)
Mỗi phần tử liên kết với phần tử đứng liền sau trong danh sách
Mỗi phần tử trong danh sách liên kết đơn là một cấu trúc có hai thành phần
Thành phần dữ liệu: Lưu trữ thông tin về bản thân phần tử
Thành phần liên kết: Lưu địa chỉ phần tử đứng sau trong danh sách hoặc bằng NULL nếu là phần tử cuối danh sách.
Cấu trúc dữ liệu của 1 nút trong List đơn
typedef struct tagNode
{ Data Info; // Lưu thông tin bản thân
struct tagNode *pNext; //Lưu địa chỉ của Node đứng sau
}Node;
Cấu trúc dữ liệu của DSLK đơn
typedef struct tagList
{ Node *pHead;//Lưu địa chỉ Node đầu tiên trong List
Node *pTail; //Lưu địa chỉ của Node cuối cùng trong List
}LIST; // kiểu danh sách liên kết đơn
*các thao tác cơ bản trên danh sách liên kết
Tạo 1 danh sách liên kết đơn rỗng
Tạo 1 nút có trường Infor bằng x
Tìm một phần tử có Info bằng x
Thêm một phần tử có khóa x vào danh sách
Hủy một phần tử trong danh sách
Duyệt danh sách
Sắp xếp danh sách liên kết đơn
*khởi tạo danh ách liên kết
Địa chỉ của nút đầu tiên, địa chỉ của nút cuối cùng đều không có
void CreateList(List &l)
{
l.pHead=NULL;
l.pTail=NULL;
}
*tạo 1 phần tử mới
Hàm trả về địa chỉ phần tử mới tạo
Node* CreateNode(Data x) // trong bài học là int
{ Node *p;
p = new Node;//Cấp phát vùng nhớ cho phần tử
if ( p==NULL) exit(1);
p ->Info = x; //gán dữa liệu cho nút
p->pNext = NULL;
return p;
}
*thêm 1 phần tử vào sánh sách liên kết
Nguyên tắc thêm: Khi thêm 1 phần tử vào List thì có làm cho pHead, pTail thay đổi?
Các vị trí cần thêm 1 phần tử vào List:
+)Thêm vào đầu List đơn
Thêm nút p vào đầu danh sách liên kết đơn
Bắt đầu:
Nếu List rỗng thì
+ pHead = p;
+ pTail = pHead;
Ngược lại
+ p->pNext = pHead;
+ pHead = p
void AddHead(LIST &l, Node* p)
{
if (l.pHead==NULL)
{
l.pHead = p;
l.pTail = l.pHead;
}
else
{
p->pNext = l.pHead;
l.pHead = p;
}
}
+)Thêm vào cuối List
Ta cần thêm nút p vào cuối list đơn
Bắt đầu:
Nếu List rỗng thì
+ pHead = p;
+ pTail = pHead;
Ngược lại
+ pTail->pNext=p;
+ pTail=p
void AddTail(LIST &l, Node *p)
{
if (l.pHead==NULL)
{
l.pHead = p;
l.pTail = l.pHead;
}
else
{
l.pTail->Next = p;
l.pTail = p;
}
}
+)Thêm vào sau 1 phần tử q trong list
Ta cần thêm nút p vào sau nút q trong list đơn
Bắt đầu:
Nếu (q!=NULL) thì
B1: p->pNext = q->pNext
B2:
+ q->pNext = p
+ nếu q = pTail thì
pTail=p
void InsertAfterQ(List &l, Node *p, Node *q)
{
if(q!=NULL)
{
p->pNext=q->Next;
q->pNext=p;
if(l.pTail==q)
l.Tail=p;
}
else
AddHead(l,p);// thêm q vào đầu list
}
*hủy phần tử trong sanh sách liên kết
Nguyên tắc: Phải cô lập phần tử cần hủy trước hủy.
Các vị trị cần hủy
Hủy phần tử đứng đầu List
Hủy phần tử có khoá bằng x
Huỷ phần tử đứng sau q trong danh sách liên kết đơn
Ở phần trên, các phần tử trong DSLK đơn được cấp phát vùng nhớ động bằng hàm new, thì sẽ được giải phóng vùng nhớ bằng hàm delete.
Bắt đầu:
Nếu (pHead!=NULL) thì
B1: p=pHead
B2:
+ pHead = pHead->pNext
+ delete (p)
B3:
Nếu pHead==NULL thì pTail=NULL
Hủy được hàm trả về 1, ngược lại hàm trả về 0
int RemoveHead(List &l, int &x)
{ Node *p;
if(l.pHead!=NULL)
{ p=l.pHead;
x=p->Info; //lưu Data của nút cần hủy
l.pHead=l.pHead->pNext;
delete p;
if(l.pHead==NULL)
l.pTail=NULL;
return 1;
}
return 0;
}
Hủy phần tử sau phần tử q trong List
Bắt đầu
Nếu (q!=NULL) thì //q tồn tại trong List
B1: p=q->pNext;// p là phần tử cần hủy
B2: Nếu (p!=NULL) thì // q không phải là phần tử cuối
+ q->pNext=p->pNext;// tách p ra khỏi xâu
+ nếu (p== pTail) // nút cần hủy là nút cuối
pTail=q;
+ delete p;// hủy p
int RemoveAfterQ(List &l, Node *q, int &x)
{ Node *p;
if(q!=NULL)
{ p=q->pNext; //p là nút cần xoá
if(p!=NULL) // q không phài là nút cuối
{ if(p==l.pTail) //nút cần xoá là nút cuối cùng
l.pTail=q;// cập nhật lạ pTail
q->pNext=p->pNext; x=p->Info;
delete p;
}
return 1;
}
else
return 0; }
Thuật toán hủy phần tử có khoá x
Bước 1:
Tìm phần tử p có khoá bằng x, và q đứng trước p
Bước 2:
Nếu (p!=NULL) thì //tìm thấy phần tử có khoá bằng x
Hủy p ra khỏi List bằng cách hủy phần tử đứng sau q
Ngược lại
Báo không tìm thấy phần tử có khoá
int RemoveX(List &l, int x)
{ Node *p,*q = NULL; p=l.Head;
while((p!=NULL)&&(p->Info!=x)) //tìm
{ q=p;
p=p->Next;
}
if(p==NULL) //không tìm thấy phần tử có khoá bằng x
return 0;
if(q!=NULL)//tìm thấy phần tử có khoá bằng x
DeleteAfterQ(l,q,x);
else //phần tử cần xoá nằm đầu List
RemoveHead(l,x);
return 1;
}
Hàm tìm 1 phần tử trong DSLK đơn
Hàm tìm phần tử có Info = x, hàm trả về địa chỉ của nút có Info = x, ngược lại hàm trả về NULL
Node *Search(LIST l, Data x)
{
Node *p;
p = l.pHead;
while((p!= NULL)&&(p->Info != x))
p = p->pNext;
return p;
}
Duyệt danh sách
Duyệt danh sách là thao tác thường được thực hiện khi có nhu cầu cần xử lý các phần tử trong danh sách như:
Đếm các phần tử trong danh sách
Tìm tất cả các phần tử trong danh sách thảo điều kiện
Hủy toàn bộ danh sách
Bước 1:
p = pHead;// p lưu địa chỉ của phần tử đầu trong List
Bước 2:
Trong khi (danh sách chưa hết) thực hiện
+ xử lý phần tử p
+ p=p->pNext;// qua phần tử kế
void PrintList(List l)
{
Node *p;
p=l.pHead;
while(p!=NULL)
{ printf(“%d ”, p->Info);
p=p->pNext;
}
}
Hủy danh sách liên kết đơn
Bước 1:
Trong khi (danh sách chưa hết) thực hiện
B11:
p = pHead;
pHead = pHead->pNext;// cập nhật pHead
B12:
Hủy p
Bước 2:
pTail = NULL;// bảo toàn tính nhất quán khi xâu rỗng
void RemoveList(List &l)
{
Node *p;
while(l.pHead!=NULL)//còn phần tử trong List
{
p = l.pHead;
l.pHead = p->pNext;
delete p;
}
}
Sắp xếp danh sách
Có hai cách tiếp cận
Cách 1: Thay đổi thành phần Info
Cách 2: Thay đổi thành phần pNext (thay đổi trình tự móc nối của các phần tử sao cho tạo lập nên được thứ tự mong muốn)
Thay đổi thành phần Info (dữ liệu)
Ưu: Cài đặt đơn giản, tương tự như sắp xếp mảng
Nhược:
Đòi hỏi thêm vùng nhớ khi hoán vị nội dung của 2 phần tử -> chỉ phù hợp với những xâu có kích thước Info nhỏ
Khi kích thước Info (dữ liệu) lớn chi phí cho việc hoán vị thành phần Info lớn
Làm cho thao tác sắp xếp chậm
Thay đổi thành phần pNext
Ưu:
Kích thước của trường này không thay đổi, do đó không phụ thuộc vào kích thước bản chất dữ liệu lưu tại mỗi nút.
Thao tác sắp xếp nhanh
Nhược: Cài đặt phức tạp
void SelectionSort(LIST &l)
{
Node *p,*q,*min;
p=l.pHead;
while(p!=l.pTail)
{
min=p;
q=p->pNext;
--------------------------------------
while(q!=NULL)
{
if(q->Info<p->Info)
min=q;
q=q->pNext;
}
HV(min->Info,p->Info);
p=p->pNext;
}
}
Các thuật toán sắp xếp hiệu quả trên List
Các thuật toán sắp xếp xâu (List) bằng các thay đổi thành phần pNext (thành phần liên kết) có hiệu quả cao như:
Thuật toán sắp xếp Quick Sort
Thuật toán sắp xếp Merge Sort
Thuật toán sắp xếp Radix Sort
Thuật toán sắp xếp Quick Sort
Bước 1:
Chọn X là phần tử đầu xâu L làm phần tử cầm canh
Loại X ra khỏi L
Bước 2:
Tách xâu L ra làm 2 xâu L1(gồm các phần tử nhỏ hơn hoặc bằng x) và L2 (gồm các phần tử lớn hơn X)
Bước 3: Nếu (L1 !=NULL) thì QuickSort(L1)
Bước 4: Nếu (L2!=NULL) thì QuickSort(L2)
Bước 5: Nối L1, X, L2 lại theo thứ tự ta có xâu L đã được sắp xếp
Sắp xếp L1
Sắp xếp L2
Chọn x=6 cầm canh, và tách L2 thành L21 và L22
void QuickSort(List &l)
{ Node *p,*X;//X lưu địa chỉ của phần tử cầm canh
List l1,l2;
if(l.pHead==l.pTail) return;//đã có thứ tự
CreateList(l1);
CreateList(l2);
X=l.pHead;
l.pHead=X->pNext;
while(l.pHead!=NULL)//tách L = L1 va L2
{ p=l.pHead;
l.pHead=p->pNext;
p->pNext=NULL;
if(p->Info<=X->Info)
AddHead(l1,p);
else
AddHead(l2,p);
}
QuickSort(l1);//Gọi đệ quy sắp xếp L1
QuickSort(l2);//Gọi đệ quy sắp xếp L2
if(l1.pHead!=NULL)//nối l1, l2 va X vao l
{
l.pHead=l1.pHead;
l1.pTail->pNext=X;//nối X vào
}
else
l.pHead=X;
X->pNext=l2.pHead;
if(l2.pHead!=NULL) //l2 có trên một phần tử
l.pTail=l2.pTail;
else //l2 không có phần tử nào
l.pTail=X;
}
Thuật tốn sắp xếp Merge Sort
Bước 1: Phân phối luân phiên từng đường chạy của xâu L vào 2 xâu con L1 và L2.
Bước 2: Nếu L1 != NULL thì Merge Sort (L1).
Bước 3: Nếu L2 != NULL thì Merge Sort (L2).
Bước 4: Trộn L1 và L2 đã sắp xếp lại ta có xâu L đã được sắp xếp.
Không tốn thêm không gian lưu trữ cho các dãy phụ
Cài đặt hàm main()
Yêu cầu: Viết chương trình thành lập 1 xâu đơn, trong đó thành phần dữ liệu của mỗi nút là 1 số nguyên dương.
Liệt kê tất thành phần dữ liệu của tất cả các nút trong xâu
Tìm 1 phần tử có khoá bằng x trong xâu.
Xoá 1 phần tử đầu xâu
Xoá 1 phần tử có khoá bằng x trong xâu
Sắp xếp xâu tăng dần theo thành phần dữ liệu (Info)
Chèn 1 phần tử vào xâu, sao cho sau khi chèn xâu vẫn tăng dần theo trường dữ liệu
..vv
void main()
{ LIST l1; Node *p; int x;
CreateList(l1);
do{
printf(“nhap x=”); scanf(“%d”,&x);
if(x>0)
{ p = CreateNode(x);
AddHead(l1,x);
}
}while(x>0);
printf(“Danh sách mới thành lập là\n”);
PrintList(l1);
printf(“nhập x cần tìm x=”); scanf(“%d”,&x);
p = Search(l1,x);
if(p==NULL) printf(“không tìm thấy”);
else printf(“tìm thấy”);
RemoveHead(l1,x);
printf(“danh sách sau khi xóa\n”);
PrintList(l1);
printf(“nhập khoá cần xoá\n”);
scanf(“%d”,&x);
RemoveX(l1,x);
printf(“danh sách sau khi xoá”);
PrintfList(l1);
SelectionSort(l1);
printf(“Danh sách sau khi sắp xếp”);
PrintfList(l1);
RemoveList(l1);
}
Mỗi phần tử trong danh sách liên kết đơn là một cấu trúc có hai thành phần
Thành phần dữ liệu: Lưu trữ thông tin về bản thân phần tử
Thành phần liên kết: Lưu địa chỉ phần tử đứng sau trong danh sách hoặc bằng NULL nếu là phần tử cuối danh sách.
Cấu trúc dữ liệu của 1 nút trong List đơn
typedef struct tagNode
{ Data Info; // Lưu thông tin bản thân
struct tagNode *pNext; //Lưu địa chỉ của Node đứng sau
}Node;
Cấu trúc dữ liệu của DSLK đơn
typedef struct tagList
{ Node *pHead;//Lưu địa chỉ Node đầu tiên trong List
Node *pTail; //Lưu địa chỉ của Node cuối cùng trong List
}LIST; // kiểu danh sách liên kết đơn
*các thao tác cơ bản trên danh sách liên kết
Tạo 1 danh sách liên kết đơn rỗng
Tạo 1 nút có trường Infor bằng x
Tìm một phần tử có Info bằng x
Thêm một phần tử có khóa x vào danh sách
Hủy một phần tử trong danh sách
Duyệt danh sách
Sắp xếp danh sách liên kết đơn
*khởi tạo danh ách liên kết
Địa chỉ của nút đầu tiên, địa chỉ của nút cuối cùng đều không có
void CreateList(List &l)
{
l.pHead=NULL;
l.pTail=NULL;
}
*tạo 1 phần tử mới
Hàm trả về địa chỉ phần tử mới tạo
Node* CreateNode(Data x) // trong bài học là int
{ Node *p;
p = new Node;//Cấp phát vùng nhớ cho phần tử
if ( p==NULL) exit(1);
p ->Info = x; //gán dữa liệu cho nút
p->pNext = NULL;
return p;
}
*thêm 1 phần tử vào sánh sách liên kết
Nguyên tắc thêm: Khi thêm 1 phần tử vào List thì có làm cho pHead, pTail thay đổi?
Các vị trí cần thêm 1 phần tử vào List:
+)Thêm vào đầu List đơn
Thêm nút p vào đầu danh sách liên kết đơn
Bắt đầu:
Nếu List rỗng thì
+ pHead = p;
+ pTail = pHead;
Ngược lại
+ p->pNext = pHead;
+ pHead = p
void AddHead(LIST &l, Node* p)
{
if (l.pHead==NULL)
{
l.pHead = p;
l.pTail = l.pHead;
}
else
{
p->pNext = l.pHead;
l.pHead = p;
}
}
+)Thêm vào cuối List
Ta cần thêm nút p vào cuối list đơn
Bắt đầu:
Nếu List rỗng thì
+ pHead = p;
+ pTail = pHead;
Ngược lại
+ pTail->pNext=p;
+ pTail=p
void AddTail(LIST &l, Node *p)
{
if (l.pHead==NULL)
{
l.pHead = p;
l.pTail = l.pHead;
}
else
{
l.pTail->Next = p;
l.pTail = p;
}
}
+)Thêm vào sau 1 phần tử q trong list
Ta cần thêm nút p vào sau nút q trong list đơn
Bắt đầu:
Nếu (q!=NULL) thì
B1: p->pNext = q->pNext
B2:
+ q->pNext = p
+ nếu q = pTail thì
pTail=p
void InsertAfterQ(List &l, Node *p, Node *q)
{
if(q!=NULL)
{
p->pNext=q->Next;
q->pNext=p;
if(l.pTail==q)
l.Tail=p;
}
else
AddHead(l,p);// thêm q vào đầu list
}
*hủy phần tử trong sanh sách liên kết
Nguyên tắc: Phải cô lập phần tử cần hủy trước hủy.
Các vị trị cần hủy
Hủy phần tử đứng đầu List
Hủy phần tử có khoá bằng x
Huỷ phần tử đứng sau q trong danh sách liên kết đơn
Ở phần trên, các phần tử trong DSLK đơn được cấp phát vùng nhớ động bằng hàm new, thì sẽ được giải phóng vùng nhớ bằng hàm delete.
Bắt đầu:
Nếu (pHead!=NULL) thì
B1: p=pHead
B2:
+ pHead = pHead->pNext
+ delete (p)
B3:
Nếu pHead==NULL thì pTail=NULL
Hủy được hàm trả về 1, ngược lại hàm trả về 0
int RemoveHead(List &l, int &x)
{ Node *p;
if(l.pHead!=NULL)
{ p=l.pHead;
x=p->Info; //lưu Data của nút cần hủy
l.pHead=l.pHead->pNext;
delete p;
if(l.pHead==NULL)
l.pTail=NULL;
return 1;
}
return 0;
}
Hủy phần tử sau phần tử q trong List
Bắt đầu
Nếu (q!=NULL) thì //q tồn tại trong List
B1: p=q->pNext;// p là phần tử cần hủy
B2: Nếu (p!=NULL) thì // q không phải là phần tử cuối
+ q->pNext=p->pNext;// tách p ra khỏi xâu
+ nếu (p== pTail) // nút cần hủy là nút cuối
pTail=q;
+ delete p;// hủy p
int RemoveAfterQ(List &l, Node *q, int &x)
{ Node *p;
if(q!=NULL)
{ p=q->pNext; //p là nút cần xoá
if(p!=NULL) // q không phài là nút cuối
{ if(p==l.pTail) //nút cần xoá là nút cuối cùng
l.pTail=q;// cập nhật lạ pTail
q->pNext=p->pNext; x=p->Info;
delete p;
}
return 1;
}
else
return 0; }
Thuật toán hủy phần tử có khoá x
Bước 1:
Tìm phần tử p có khoá bằng x, và q đứng trước p
Bước 2:
Nếu (p!=NULL) thì //tìm thấy phần tử có khoá bằng x
Hủy p ra khỏi List bằng cách hủy phần tử đứng sau q
Ngược lại
Báo không tìm thấy phần tử có khoá
int RemoveX(List &l, int x)
{ Node *p,*q = NULL; p=l.Head;
while((p!=NULL)&&(p->Info!=x)) //tìm
{ q=p;
p=p->Next;
}
if(p==NULL) //không tìm thấy phần tử có khoá bằng x
return 0;
if(q!=NULL)//tìm thấy phần tử có khoá bằng x
DeleteAfterQ(l,q,x);
else //phần tử cần xoá nằm đầu List
RemoveHead(l,x);
return 1;
}
Hàm tìm 1 phần tử trong DSLK đơn
Hàm tìm phần tử có Info = x, hàm trả về địa chỉ của nút có Info = x, ngược lại hàm trả về NULL
Node *Search(LIST l, Data x)
{
Node *p;
p = l.pHead;
while((p!= NULL)&&(p->Info != x))
p = p->pNext;
return p;
}
Duyệt danh sách
Duyệt danh sách là thao tác thường được thực hiện khi có nhu cầu cần xử lý các phần tử trong danh sách như:
Đếm các phần tử trong danh sách
Tìm tất cả các phần tử trong danh sách thảo điều kiện
Hủy toàn bộ danh sách
Bước 1:
p = pHead;// p lưu địa chỉ của phần tử đầu trong List
Bước 2:
Trong khi (danh sách chưa hết) thực hiện
+ xử lý phần tử p
+ p=p->pNext;// qua phần tử kế
void PrintList(List l)
{
Node *p;
p=l.pHead;
while(p!=NULL)
{ printf(“%d ”, p->Info);
p=p->pNext;
}
}
Hủy danh sách liên kết đơn
Bước 1:
Trong khi (danh sách chưa hết) thực hiện
B11:
p = pHead;
pHead = pHead->pNext;// cập nhật pHead
B12:
Hủy p
Bước 2:
pTail = NULL;// bảo toàn tính nhất quán khi xâu rỗng
void RemoveList(List &l)
{
Node *p;
while(l.pHead!=NULL)//còn phần tử trong List
{
p = l.pHead;
l.pHead = p->pNext;
delete p;
}
}
Sắp xếp danh sách
Có hai cách tiếp cận
Cách 1: Thay đổi thành phần Info
Cách 2: Thay đổi thành phần pNext (thay đổi trình tự móc nối của các phần tử sao cho tạo lập nên được thứ tự mong muốn)
Thay đổi thành phần Info (dữ liệu)
Ưu: Cài đặt đơn giản, tương tự như sắp xếp mảng
Nhược:
Đòi hỏi thêm vùng nhớ khi hoán vị nội dung của 2 phần tử -> chỉ phù hợp với những xâu có kích thước Info nhỏ
Khi kích thước Info (dữ liệu) lớn chi phí cho việc hoán vị thành phần Info lớn
Làm cho thao tác sắp xếp chậm
Thay đổi thành phần pNext
Ưu:
Kích thước của trường này không thay đổi, do đó không phụ thuộc vào kích thước bản chất dữ liệu lưu tại mỗi nút.
Thao tác sắp xếp nhanh
Nhược: Cài đặt phức tạp
void SelectionSort(LIST &l)
{
Node *p,*q,*min;
p=l.pHead;
while(p!=l.pTail)
{
min=p;
q=p->pNext;
--------------------------------------
while(q!=NULL)
{
if(q->Info<p->Info)
min=q;
q=q->pNext;
}
HV(min->Info,p->Info);
p=p->pNext;
}
}
Các thuật toán sắp xếp hiệu quả trên List
Các thuật toán sắp xếp xâu (List) bằng các thay đổi thành phần pNext (thành phần liên kết) có hiệu quả cao như:
Thuật toán sắp xếp Quick Sort
Thuật toán sắp xếp Merge Sort
Thuật toán sắp xếp Radix Sort
Thuật toán sắp xếp Quick Sort
Bước 1:
Chọn X là phần tử đầu xâu L làm phần tử cầm canh
Loại X ra khỏi L
Bước 2:
Tách xâu L ra làm 2 xâu L1(gồm các phần tử nhỏ hơn hoặc bằng x) và L2 (gồm các phần tử lớn hơn X)
Bước 3: Nếu (L1 !=NULL) thì QuickSort(L1)
Bước 4: Nếu (L2!=NULL) thì QuickSort(L2)
Bước 5: Nối L1, X, L2 lại theo thứ tự ta có xâu L đã được sắp xếp
Sắp xếp L1
Sắp xếp L2
Chọn x=6 cầm canh, và tách L2 thành L21 và L22
void QuickSort(List &l)
{ Node *p,*X;//X lưu địa chỉ của phần tử cầm canh
List l1,l2;
if(l.pHead==l.pTail) return;//đã có thứ tự
CreateList(l1);
CreateList(l2);
X=l.pHead;
l.pHead=X->pNext;
while(l.pHead!=NULL)//tách L = L1 va L2
{ p=l.pHead;
l.pHead=p->pNext;
p->pNext=NULL;
if(p->Info<=X->Info)
AddHead(l1,p);
else
AddHead(l2,p);
}
QuickSort(l1);//Gọi đệ quy sắp xếp L1
QuickSort(l2);//Gọi đệ quy sắp xếp L2
if(l1.pHead!=NULL)//nối l1, l2 va X vao l
{
l.pHead=l1.pHead;
l1.pTail->pNext=X;//nối X vào
}
else
l.pHead=X;
X->pNext=l2.pHead;
if(l2.pHead!=NULL) //l2 có trên một phần tử
l.pTail=l2.pTail;
else //l2 không có phần tử nào
l.pTail=X;
}
Thuật tốn sắp xếp Merge Sort
Bước 1: Phân phối luân phiên từng đường chạy của xâu L vào 2 xâu con L1 và L2.
Bước 2: Nếu L1 != NULL thì Merge Sort (L1).
Bước 3: Nếu L2 != NULL thì Merge Sort (L2).
Bước 4: Trộn L1 và L2 đã sắp xếp lại ta có xâu L đã được sắp xếp.
Không tốn thêm không gian lưu trữ cho các dãy phụ
Cài đặt hàm main()
Yêu cầu: Viết chương trình thành lập 1 xâu đơn, trong đó thành phần dữ liệu của mỗi nút là 1 số nguyên dương.
Liệt kê tất thành phần dữ liệu của tất cả các nút trong xâu
Tìm 1 phần tử có khoá bằng x trong xâu.
Xoá 1 phần tử đầu xâu
Xoá 1 phần tử có khoá bằng x trong xâu
Sắp xếp xâu tăng dần theo thành phần dữ liệu (Info)
Chèn 1 phần tử vào xâu, sao cho sau khi chèn xâu vẫn tăng dần theo trường dữ liệu
..vv
void main()
{ LIST l1; Node *p; int x;
CreateList(l1);
do{
printf(“nhap x=”); scanf(“%d”,&x);
if(x>0)
{ p = CreateNode(x);
AddHead(l1,x);
}
}while(x>0);
printf(“Danh sách mới thành lập là\n”);
PrintList(l1);
printf(“nhập x cần tìm x=”); scanf(“%d”,&x);
p = Search(l1,x);
if(p==NULL) printf(“không tìm thấy”);
else printf(“tìm thấy”);
RemoveHead(l1,x);
printf(“danh sách sau khi xóa\n”);
PrintList(l1);
printf(“nhập khoá cần xoá\n”);
scanf(“%d”,&x);
RemoveX(l1,x);
printf(“danh sách sau khi xoá”);
PrintfList(l1);
SelectionSort(l1);
printf(“Danh sách sau khi sắp xếp”);
PrintfList(l1);
RemoveList(l1);
}
###
[sắp xếp trộn run sắp xếp ngoại](http://www.thuattoan.net/2015/04/sap-xep-tron-run-sap-xep-ngoai.html)
Phương pháp trộn Run
Khái niệm cơ bản:
Run là một dãy liên tiếp các phần tử được sắp thứ tự. Ví dụ 2 4 7 12 50 là một run gồm có 5 phần tử
Chiều dài run chính là số phần tử trong Run. Chẳng hạn, run trong ví dụ trên có chiều dài là 5.
7 8 5 3 9 12 4 23 78 90 45 54
Giải thuật: Giải thuật sắp xếp tập tin bằng phương pháp trộn run có thể tóm lược như sau: Input: f0 là tập tin cần sắp thứ tự. Output: f0 là tập tin đã được sắp thứ tự. Gọi f1, f2 là 2 tập tin trộn. Các tập tin f0, f1, f2 có thể là các tập tin tuần tự (text file) hay có thể là các tập tin nhị phân.
Bước 1:
- Giả sử các phần tử trên f0 là: 24 12 67 33 58 42 11 34 29 31
- Khởi tạo f1, f2 rỗng
- Thực hiện phân bố m=1 phần tử lần lượt từ f0 vào f1 và f2:
f1: 24 67 58 11 29 f2: 12 33 42 34 31
Trộn f1, f2 thành f0:
f0: 12 24 33 67 42 58 11 34 29 31
Bước 2:
-Phân bố m=2 phần tử lần lượt từ f0 vào f1 và f2:
f1: 12 24 42 58 29 31
f0: 12 24 33 67 42 58 11 34 29 31
f2: 33 67 11 34
- Trộn f1, f2 thành f0: f1: 12 24 42 58 29 31 f0: 12 24 33 67 11 34 42 58 29 31 f2: 33 67 11 34
Bước 3: - Tương tự bước 2, phân bố m=4 phần tử lần lượt từ f0 vào f1 và f2, kết quả thu được như sau: f1: 12 24 33 67 29 31 f2: 11 34 42 58 - Trộn f1, f2 thành f0: f0: 11 12 24 33 34 42 58 67 29 31
Bước 4: - Phân bố m=8 phần tử lần lượt từ f0 vào f1 và f2: f1: 11 12 24 33 34 42 58 67 f2: 29 31 - Trộn f1, f2 thành f0: f0: 11 12 24 29 31 33 34 42 58 67
Bước 5: Lặp lại tương tự các bước trên, cho đến khi chiều dài m của run cần phân bổ lớn hơn chiều dài n của f0 thì dừng.
void chia(FILE *a,FILE *b,FILE *c,int p) void main (void) { FILE *a,*b,*c; tao_file(); xuat_file(); p = 1; while (p < n) { chia(a,b,c,p); tron(b,c,a,p); p=2*p; } }
void chia(FILE *a,FILE *b,FILE *c,int p) while (!feof(a)) { /*Chia p phan tu cho b*/ dem=0; while ((dem<p) && (!feof(a))) { fscanf(a,"%3d",&x); fprintf(b,"%3d",x); dem++; }
dem=0; while ((dem<p) && (!feof(a))) { fscanf(a,"%3d",&x); fprintf(c,"%3d",x); dem++; } }
void tron(FILE *b,FILE *c,FILE *a,int p) int stop,x,y,l,r; a=fopen("d:\ctdl\sortfile\bang.int","wb"); b=fopen("d:\ctdl\sortfile\bang1.int","rb"); c=fopen("d:\ctdl\sortfile\bang2.int","rb"); while ((!feof(b)) && (!feof(c))) { l=0;/*so phan tu cua b da ghi len a*/ r=0;/*so phan tu cua c da ghi len a*/ fscanf(b,"%3d",&x); fscanf(c,"%3d",&y); stop=0;
while ((l!=p) && (r!=p) && (!stop)) { if (x<y) { fprintf(a,"%3d",x); l++; if ((l<p) && (!feof(b))) /*chua du p phan tu va chua het file b*/ fscanf(b,"%3d",&x); else { fprintf(a,"%3d",y); r++; if (feof(b)) stop=1; } }
else
{
fprintf(a,"%3d",y); r++; if ((r<p) && (!feof(c))) /*chua du p phan tu va chua het file c*/ fscanf(c,"%3d",&y); else {
fprintf(a,"%3d",x); l++; if (feof(c)) stop=1; } } } //Chep phan con lai cua p phan tu tren b len a
while ((!feof(b)) && (l<p)) { fscanf(b,"%3d",&x); fprintf(a,"%3d",x); l++; }
//Chep phan con lai cua p phan tu tren c len a while ((!feof(c)) && (r<p)) { fscanf(c,"%3d",&y); fprintf(a,"%3d",y); r++; } } if (!feof(b)) { /*chep phan con lai cua b len a*/ while (!feof(b)) { fscanf(b,"%3d",&x); fprintf(a,"%3d",x); } }
{
fscanf(c,"%3d",&x); fprintf(a,"%3d",x);
} } fclose(a); fclose(b); fclose(c); }
/*Chia p phan tu cho c*/ dem=0; while ((dem<p) && (!feof(a))) { fscanf(a,"%3d",&x); fprintf(c,"%3d",x); dem++; } }
Khái niệm cơ bản:
Run là một dãy liên tiếp các phần tử được sắp thứ tự. Ví dụ 2 4 7 12 50 là một run gồm có 5 phần tử
Chiều dài run chính là số phần tử trong Run. Chẳng hạn, run trong ví dụ trên có chiều dài là 5.
7 8 5 3 9 12 4 23 78 90 45 54
Giải thuật: Giải thuật sắp xếp tập tin bằng phương pháp trộn run có thể tóm lược như sau: Input: f0 là tập tin cần sắp thứ tự. Output: f0 là tập tin đã được sắp thứ tự. Gọi f1, f2 là 2 tập tin trộn. Các tập tin f0, f1, f2 có thể là các tập tin tuần tự (text file) hay có thể là các tập tin nhị phân.
Bước 1:
- Giả sử các phần tử trên f0 là: 24 12 67 33 58 42 11 34 29 31
- Khởi tạo f1, f2 rỗng
- Thực hiện phân bố m=1 phần tử lần lượt từ f0 vào f1 và f2:
f1: 24 67 58 11 29 f2: 12 33 42 34 31
Trộn f1, f2 thành f0:
f0: 12 24 33 67 42 58 11 34 29 31
Bước 2:
-Phân bố m=2 phần tử lần lượt từ f0 vào f1 và f2:
f1: 12 24 42 58 29 31
f0: 12 24 33 67 42 58 11 34 29 31
f2: 33 67 11 34
- Trộn f1, f2 thành f0: f1: 12 24 42 58 29 31 f0: 12 24 33 67 11 34 42 58 29 31 f2: 33 67 11 34
Bước 3: - Tương tự bước 2, phân bố m=4 phần tử lần lượt từ f0 vào f1 và f2, kết quả thu được như sau: f1: 12 24 33 67 29 31 f2: 11 34 42 58 - Trộn f1, f2 thành f0: f0: 11 12 24 33 34 42 58 67 29 31
Bước 4: - Phân bố m=8 phần tử lần lượt từ f0 vào f1 và f2: f1: 11 12 24 33 34 42 58 67 f2: 29 31 - Trộn f1, f2 thành f0: f0: 11 12 24 29 31 33 34 42 58 67
Bước 5: Lặp lại tương tự các bước trên, cho đến khi chiều dài m của run cần phân bổ lớn hơn chiều dài n của f0 thì dừng.
void chia(FILE *a,FILE *b,FILE *c,int p) void main (void) { FILE *a,*b,*c; tao_file(); xuat_file(); p = 1; while (p < n) { chia(a,b,c,p); tron(b,c,a,p); p=2*p; } }
void chia(FILE *a,FILE *b,FILE *c,int p) while (!feof(a)) { /*Chia p phan tu cho b*/ dem=0; while ((dem<p) && (!feof(a))) { fscanf(a,"%3d",&x); fprintf(b,"%3d",x); dem++; }
dem=0; while ((dem<p) && (!feof(a))) { fscanf(a,"%3d",&x); fprintf(c,"%3d",x); dem++; } }
void tron(FILE *b,FILE *c,FILE *a,int p) int stop,x,y,l,r; a=fopen("d:\ctdl\sortfile\bang.int","wb"); b=fopen("d:\ctdl\sortfile\bang1.int","rb"); c=fopen("d:\ctdl\sortfile\bang2.int","rb"); while ((!feof(b)) && (!feof(c))) { l=0;/*so phan tu cua b da ghi len a*/ r=0;/*so phan tu cua c da ghi len a*/ fscanf(b,"%3d",&x); fscanf(c,"%3d",&y); stop=0;
while ((l!=p) && (r!=p) && (!stop)) { if (x<y) { fprintf(a,"%3d",x); l++; if ((l<p) && (!feof(b))) /*chua du p phan tu va chua het file b*/ fscanf(b,"%3d",&x); else { fprintf(a,"%3d",y); r++; if (feof(b)) stop=1; } }
else
{
fprintf(a,"%3d",y); r++; if ((r<p) && (!feof(c))) /*chua du p phan tu va chua het file c*/ fscanf(c,"%3d",&y); else {
fprintf(a,"%3d",x); l++; if (feof(c)) stop=1; } } } //Chep phan con lai cua p phan tu tren b len a
while ((!feof(b)) && (l<p)) { fscanf(b,"%3d",&x); fprintf(a,"%3d",x); l++; }
//Chep phan con lai cua p phan tu tren c len a while ((!feof(c)) && (r<p)) { fscanf(c,"%3d",&y); fprintf(a,"%3d",y); r++; } } if (!feof(b)) { /*chep phan con lai cua b len a*/ while (!feof(b)) { fscanf(b,"%3d",&x); fprintf(a,"%3d",x); } }
{
fscanf(c,"%3d",&x); fprintf(a,"%3d",x);
} } fclose(a); fclose(b); fclose(c); }
/*Chia p phan tu cho c*/ dem=0; while ((dem<p) && (!feof(a))) { fscanf(a,"%3d",&x); fprintf(c,"%3d",x); dem++; } }
###
[thư viện vector STL C++](http://www.thuattoan.net/2015/04/thu-vien-vector-stl-c.html)
**SỬ DỤNG STL VECTOR TRONG C++** *Nguyễn Trí Hải* *11520094* *KHMT06* *I) Giới thiệu:*
Lớp mảng động vector<T>có sẵn trong thư viện chuẩn STL của C++ cho phép định nghĩa một mảng động các phần tử kiểu T, vector có các tính chất sau:
- Không cần phải khai báo kích thước của mảng vector có thể tự động cấp phát bộ nhớ, bạn sẽ không phải quan tâm đến quản lý kích thước của nó.
- Vector còn có thể cho bạn biết số lượng các phần tử mà bạn đang lưu trong nó.
- Vector có các phương thức của stack.
- Hỗ trợ tất cả các thao tác cơ bản như chèn ,xóa, sao chép ..
*II) Vì sao dùng Vector:*
| || || || || || || || || || |
à…
Kiểu vector có thể coi là kiểu mảng trong lập trình C truyền thống. Mảng là tập hợp các giá trị cùng kiểu, được sắp xếp nối tiếp nhau. Các phần tử của mảng có thể được truy cập ngẫu nhiên qua chỉ số.
Vấn đề đặt ra:
**Nếu vector là mảng thì tại sao lại phải sử dụng vector khi bạn đã quá quen thuộc với mảng?**
- Nếu bạn sử dụng mảng tĩnh: Mảng này luôn được khai báo với kích thước tối đa mà bạn có thể dùng dẫn đến tốn nhiều vùng nhớ thừa.
- Nếu bạn sử dụng mảng động: Bạn phải xin cấp phát bộ nhớ, làm việc với con trỏ. Con trỏ là
khái niệm hay trong C, C++, nhưng nó là nguyên nhân của rất nhiều rắc rối trong lập trình.
- Không thuận tiện trong việc truyền tham số kiểu mảng vào hàm hay trả lại kiểu mảng từ hàm.
- Nhược điểm quan trọng nhất: Nếu bạn sử dụng mảng vượt chỉ số vượt quá kích thước đã khai báo, C++ sẽ không thông báo lỗi, điều này dẫn đến lỗi dây chuyền do các lệnh lỗi đã tác động đến các biến khác trong chương trình
Vector là một container cung cấp khả năng sử dụng mảng mềm dẻo, có kiểm soát range check khi cần thiết, với kích thước tùy ý (mà không cần phải sử dụng con trỏ). Ngoài ra vector cho phép bạn chèn thêm hoặc xóa đi một số phần tử chỉ bằng 1 lệnh (không phải sử dụng vòng lặp như đối với mảng).
*III) Cú pháp:*
Để dùng vector thì cần thêm 1 header #include <vector>và phải có using std::vector; vì vector được định nghĩa trong STL (Standard Template Library)
Ví dụ:
vector<int> A;
Câu lệnh trên định nghĩa 1 vector có kiểu int. Kiểu vector được đặt trong 2 dấu ngoặc nhọn. Kích thước của vector có thể tự nâng lên nên không cần khai báo số phần tử hoặc nếu muốn khai báo thì bạn có thể khai báo như sau:
vector<int> A(10);
Câu lệnh trên khai báo A là 1 vector kiểu int có 10 phần tử. Mặc dù size của nó bằng 10 nhưng sử dụng hơn vẫn được.
Ta có thể khởi tạo giá trị mặc định cho vector:
vector<int> A(10,2);
Câu lệnh trên khai báo 10 phần tử vector A được khởi tạo bằng 2.Đồng thời ta cũng có thể khởi tạo cho 1 vector sẽ là bản sao của 1 hoặc 1 phần vector khác, ví dụ :
vector<int> A(10,2);
vector<int> B(A);
vector<int> C(A.begin(), A.begin() + 5 );
Để hiểu rõ vè vector, ta xem đoạn code sau:
#include<iostream> // Thư viện iostream phục vụ ghi dữ liệu ra màn hình
#include<vector> // Thư viện vector, sử dụng kiểu vector
usingnamespace std; // Sử dụng namespace std
int main()
{
vector<int> V(3);
// V kiểu vector số nguyên (sử dụng giống mảng int[3])
V[0] = 5;
// Gán giá trị cho các phần tử của biến V
V[1] = 6;
// Sử dụng dấu móc [] hoàn toàn giống với mảng
V[2] = 7;
for (int i=0; i<V.size(); i++)
// Ghi giá trị các phần tử của V ra màn hình
cout << V[i] << endl;
// Nếu sử dụng mảng, bạn phải có biến lưu kích thước
}
Ví dụ trên cho bạn thấy việc sử dụng vector rất đơn giản, hoàn toàn giống với mảng nhưng bộ nhớ được quản lý tự động, bạn không phải quan tâm đến giải phóng các vùng bộ nhớ đã xin cấp phát.
Trường hợp xác định kích thước mảng khi chương trình đang chạy, chúng ta dùng hàm dựng mặc định (default constructor) để khai báo mảng chưa xác định kích thước, sau đó dùng phương thức resize() để xác định kích thước của mảng khi cần. Chương trình sau đây nhập vào n từ (word) mỗi từ là một chuỗi kiểu string:
![](file:///C:/Users/TRANKH~1/AppData/Local/Temp/msohtmlclip1/01/clip_image001.png)
#include<iostream>
#include<string>
#include<vector>
usingnamespace std;
int main()
{
int iWordNum;
vector<string> arrWords;
cout <<"Enter number of words = ";
cin >> iWordNum;
arrWords.resize(iWordNum);
for (int i = 0; i < arrWords.size(); i ++)
{
cout <<"Enter word "<< i <<" = ";
cin >> arrWords[i];
}
cout <<"After entering data..."<< endl;
for (int i = 0; i < arrWords.size(); i ++)
cout << arrWords[i] << endl;
}
Ouput:
| |
Enter number of words = 3
Enter word 1 = hello
Enter word 1 = c++’s
Enter word 1 = world
After entering data...
hello
c++’s
world
Press any key to continue . . .
*IV) Các phương thức:* **Các phương thức của stack: push_back() và pop_back()** ![](file:///C:/Users/TRANKH~1/AppData/Local/Temp/msohtmlclip1/01/clip_image002.png)
#include<iostream>
#include<vector>
usingnamespace std;
int main()
{
int i;
vector<int> V;
for (i=0; i<5; i++)
// Lặp 5 lần, mỗi l ần đưa thêm 1 số vào vector
V.push_back(i);
// Như vậy, vector có thể được sử dụng như stack
cout << endl <<"Mang ban dau:"<< endl;
for (i=0; i<V.size(); i++)
// Ghi lại nội dung của mảng ra màn h.nh
cout << V[i] << endl;
V.pop_back( ); // Xóa phần tử vừa chèn vào đi
cout << endl <<"Xoa phan tu cuoi:"<< endl;
for (i=0; i<V.size(); i++)
// In nội dung của vector sau khi xóa
cout << V[i] << endl;
return 0;
}
Với ví dụ trên, bạn có thể thấy ta có thể sử dụng vector như 1 stack:
- Không nên dùng toán tử [] để truy xuất các phần tử mà nó không tồn tại, nghĩa là ví dụvector size = 10, mà bạn truy xuất 11 là sai. Để thêm vào 1 giá trị cho vector mà nó không có size trước hoặc đã full thì ta dùng hàm thành viên push_back(), hàm này s ẽ thêm 1 phần tửvào cuối vector.
- Tương tự với thao tác xóa một phần tử ở cuối ra khỏi vector, bạn cũng chỉ cần sử dụng 1 lệnh: pop_back( )
**Xóa tại vị trí bất kỳ, xóa trắng:**
#include<iostream>
#include<vector>
usingnamespace std;
template<classT>
void print(constvector<T>&v)
{
for (int i =0; i <v.size(); i++)
cout <<v[i] << endl;
}
int main()
{
char *chao[] = {"Xin", "chao", "tat", "ca", "cac", "ban"};
int n = sizeof(chao)/sizeof(*chao);
vector<char*> v(chao, chao + n);
//đây là 1 cách khởi tạo vector
cout <<"vector truoc khi xoa"<< endl;
print(v);
v.erase(v.begin()+ 2, v.begin()+ 5);
//xóa từ phần tử thứ 2 đến phần tử thứ 5
v.erase( v.begin()+1 );
//xóa phần tử thứ 1
cout <<"vector sau khi xoa"<< endl;
print(v);
v.clear();//Xóa toàn bộ các phần tử
cout <<"Vector sau khi clear co "
<< v.size() <<" phan tu"<< endl;
return 0;
}
Output:
| |
vector truoc khi xoa
Xin
chao
tat
ca
cac
ban
vector sau khi xoa
xin
ban
Vector sau khi clear co 0 phan tu
**Phương thức chèn**
iterator insert ( iterator position, const T& x );
void insert ( iterator position, size_type n, const T& x );
void insert ( iterator position, InputIterator first, InputIterator last );
Ví dụ:
// inserting into a vector
#include<iostream>
#include<vector>
usingnamespace std;
int main ()
{
vector<int> v1(4,100);
v1.insert ( v1.begin()+3 , 200 );
//chèn 200 vào trước vị trí thứ 3
v1.insert ( v1.begin()+2 ,2,300);
//chèn 2 lần 300 vào trước vị trí thứ 2
vector<int> v2(2,400);
int a [] = { 501, 502, 503 };
v1.insert (v1.begin()+2, a, a+3);
//chèn mảng a (3 phần tử) vào trước vị trí thứ 2
v1.insert (v1.begin()+4,v2.begin(),v2.end());
//chèn v2 vào trước vị trí thứ 4
cout <<"v1 contains:";
for (int i =0; i < v1.size(); i ++)
cout <<" "<< v1[i];
return 0;
}
Output:
| |
v1 contains: 100 100 501 502 400 400 503 100 200 300 300 100
**Một số hàm khác và chức năng** **Những toán tử so sánh:**được định nghĩa cho vector: ==, <, <=, !=, >, >= **Tham chiếu back(), front()**
template<class _TYPE, class _A>
reference vector::front( );
template<class _TYPE, class _A>
reference vector::back( );
**Trả về tham chiếu đến phần tử đầu và cuối vector:**
v.front() v[0] và v.back() v[v.size()-1]
#include<iostream>
#include<vector>
usingnamespace std;
int main ()
{
int a[] = {3,2,3,1,2,3,5,7};
int n = sizeof(a)/sizeof(*a);
vector<int> v(a, a+n);
cout <<"phan tu dau la "<< v.front() << endl;
cout <<"phan tu cuoi la "<< v.back() << endl;
cout <<"gan phan tu cuoi la 9 ..."<< endl;
v.back() = 9;
cout <<"gan phan tu dau la 100 ..."<< endl;
v.front() = 100;
cout <<"kiem tra lai vector: ";
for (int i =0; i < v.size(); i++)
cout << v[i] << “ “;
cout << endl;
return 0;
}
Output:
| |
phan tu dau la 3
phan tu cuoi la 7
gan phan tu cuoi la 9 ...
gan phan tu dau la 100 ...
kiem tra lai vector: 100 2 3 1 2 3 5 9
Press any key to continue …
**Hàm thành viên empty()**
Để xác định vector có rỗng hay không ta dùng hàm thành viên empty(), hàm này trả về true nếu vector rỗng, và false ngược lại. Cú pháp :
if(v.empty() == true) {
cout <<"No values in vector \n";
}
**- capacity() :**Trả về số lượng phần tử tối đa mà vector được cấp phát, đây là 1 con s ố có thể thay đổi do việc cấp phát bộ nhớ tự động hay bằng các hàm như reserve() và resize()
Sự khác biệt giữa 2 hàm
**size()**và **capacity() :**
#include<vector>
#include<iostream>
int main(int argc , char **argc)
{
vector<int>so1,so2[10];
so1.reserve(10);
cout <<"Kich thuoc toi da:"<<so1.capacity();
cout <<"\n Kich thuoc hien tai cua mang 2 "<<so2.size()<<endl;
return 0 ;
}
**- reserve():**cấp phát vùng nhớ cho vector, giống như **realloc()**của C và không giống **vector::resize(),**tác dụng của **reserve**để hạn chế vector tự cấp phát vùng nhớ không cần thiết.Ví dụ khi bạn thêm 1 phần tử mà vượt quá capacity thì vector sẽ cấp phát thêm, việc này lặp đi lặp lại sẽ làm giảm performance trong khi có những trường hợp ta có thểước lượng được cần sử dụng bao nhiêu bộ nhớ.
Ví dụ nếu ko có
**reserve()**thì capacity sẽ là 4 :
#include<iostream>
#include<vector>
usingnamespace std;
int main()
{
vector<int> my_vect;
my_vect.reserve( 8 );
my_vect.push_back( 1 );
my_vect.push_back( 2 );
my_vect.push_back( 3 );
cout << my_vect.capacity() <<"\n";
return 0;
}
**- swap();**hoán đổi 2 container v ới nhau (gi ống việc hoán đổi giá trị của 2 biến kiểu số). Ví dụ : v1.swap(v2); *V.Kiểm tra tràn chỉ số mảng:*
Có một vấn đề chưa được đề cập đến từ khi ta làm quen với vector, đó là khả năng kiểm tra tràn chỉ số mảng (rangecheck), để biết về khả năng này, chúng ta lại ti ếp tục với một ví dụmới :
#include<iostream>
#include<vector>
#include<conio.h>
usingnamespace std;
int main()
{
try { // sử dụng try...catch để bẫy lỗi
vector<long> V(3, 10);
// Khởi tạo vector gồm 3 thành phần
// Tất cả gán giá trị 10
cout <<"V[0]="<< V[0] << endl;
// Đưa thành phần 0 ra màn hình
cout <<"V[1]="<< V[1] << endl;
// Đưa thành phần 1 ra màn hình
cout <<"V[2]="<< V[2] << endl;
// Đưa thành phần 2 ra màn hình
cout <<"V[3]="<< V[3] << endl;
// Thành phần 3 (lệnh này hoạt động không
// đúng vì V chỉ có 3 thành phần 0,1,2
cout <<"V[4]="<< V[4] << endl;
// Thành phần 4 (càng không đúng)
// Nhưng 2 lệnh trên đều không gây lỗi
cout <<"V[0]="<< V.at(0) << endl;
// Không sử dụng [], dùng phương thức at
cout <<"V[1]="<< V.at(1) << endl;
// Thành phần 1, OK
cout <<"V[2]="<< V.at(2) << endl;
// Thành phần 2, OK
cout <<"V[3]="<< V.at(3) << endl;
// Thành phần 3: Lỗi, chương trình dừng
cout <<"V[4]="<< V.at(4) << endl;
getchar();
} catch (exception&e) {
cout <<"Tran chi so ! "<< endl;
}
return 0;
}
Trong ví dụ này, chúng ta lại có thêm một số kinh nghiệm sau:
- Nếu sử dụng cú pháp biến_vector[chỉ _số], chương trình sẽ không tạo ra lỗi khi s ử dụng chỉ số mảng nằm ngoài vùng hợp lệ (giống như mảng thường). Trong ví dụ, chúng ta mới chỉ lấy giá trị phần tử với chỉ số không hợp lệ, trường hợp này chỉ cho kết quả sai. Nhưng nếu chúng ta gán giá trị cho phần tử không hợp lệ này, hậu quả sẽnghiêm trọng hơn nhiều vì thao tác đó sẽ làm hỏng các giá trị khác trên bộ nhớ.
- Phương thức at(chỉ _số) có tác dụng tương tự như dùng ký hiệu [], nhưng có một sự khác biệt là thao tác này có kiểm tra chỉ số hợp lệ. Minh chứng cho nhận xét này trong ví dụ khi chương trình chạy đến vị trí lệnh V.at(3), lệnh này không cho ra kết quả mà tạo thành thông báo lỗi.
*VI.Mảng 2 chiều với Vector:*
#include<iostream>
#include<vector>
usingnamespace std;
int main()
{
vector<vector<int>> matrix(3, vector<int>(2,0));
//chu y viet >> de khong nham voi toan tu >>
for(int x = 0; x < 3; x++)
for(int y = 0; y < 2; y++)
matrix[x][y] = x*y;
for(int x = 0; x < 3; x++)
for(int y = 0; y < 2; y++)
cout << matrix[x][y];
cout <<'\n';
return 0;
}
Ví dụ này minh họa việc sử dụng mảng 2 chiều, thực chất đây là một vector của vector. Mảng 2 chiều sử dụng biện pháp này có thể có kích thước khác nhau giữa các d.ng (ví dụ mảng 2 chiều là nửa trên của ma trận)
*VII.Sử dụng iterator*
Container ( thùng chứa ) : Một kiểu cấu trúc dữ liệu dùng để lưu trữthông tin. Ví dụ: mảng (array), list, vector, deque...
Container nào cũng có các phương thức sau đây
| |Phương thức | |Mô tả
| |
size()
| |
Số lượng phần tử
| |
empty ()
| |
Trả về 1 nếu container rỗng, 0 nếu ngược lại.
| |
max_size()
| |
Trả về số lượng phần tử tối đa đã được cấp phát
| |
==
| |
Trả về 1 nếu hai container giống nhau
| |
!=
| |
Trả về 1 nếu hai v khác nhau
| |
begin()
| |
Trả về iterator đầu tiên của container
| |
end()
| |
Trả về iterator lặp cuối cùng của container
| |
front()
| |
Trả về tham chiếu đến phần tử đầu tiên của container
| |
back()
| |
Trả về tham chiếu đến phần tử cuối cùng của container
| |
swap()
| |
Hoán đổi 2 container với nhau (giống việc hoán đổi giá trị của 2 biến)
Trong thư viện STL thì người ta tích hợp lớp đối tượng Iterator (bộ lặp hay biến lặp) cùng với các container.Tư tưởng đó thể hiện như sau:
o Các đối tượng Iterator là các con trỏ đến các đối tượng của lớp lưu trữ:
typedef__gnu_cxx::__normal_iterator <pointer,vector_type> iterator;
o Khai báo lớp Iterator như là 1 lớp nằm trong lớp lưu trữ.
o Xác định trong lớp lưu trữ các phương thức thành phần như:
+ begin() – trả lại con trỏ kiểu đối tượng Iterartor đến phần tử đầu tiên của nằm trong đối tượng lớp lưu trữ.
+ end() – trả lại con trỏ kiểu Iterator trỏ đến 1 đối tượng nào đó bên ngoài tập các phần tử được lưu trữ. Đối tượng bên ngoài nào đó có thể có các định nghĩa khác nhau.Trong trường hợp cụ thể như vector ta có thể hiểu là trỏ đến phần tử sau phần tử cuối cùng.
o Xác định trong lớp đối tượng kiểu Iterator các toán tử như sau:
++p hoặc p++ : chuyển iterator p đến phần tử kế tiếp.
--p hoặc p-- : chuyển iterator p đến phần tử đằng trước nó.
*p : xác định giá trị của phần tử mà iterator p trỏ đến.
Như bạn biết, mảng và con trỏ có mối quan hệ chặt chẽ với nhau trong C++. Một mảng có thể được truy xuất thông qua con trỏ. Sự tương đương này trong STL là mối quan hệ giữa iterator và vector, mà tổng quát hơn là với container. Nó cung cấp cho chúng ta khả năng xử lý theo chu kì thông qua nội dung của container theo một cách giống như là bạn sử dụng con trỏ để tạo xử lý chu kỳ trong mảng.
Bạn có thể truy xuất đến các thành phần của một container bằng sử dụng một iterator:
<container> coll;
for (<container>::iterator it = coll.begin(); it != coll.end(); ++it)
{
*it;
//……..
}
Dưới đây chúng ta xét 1 ví dụ làm việc với thư viện STL với lớp vector và con trỏ kiểu iterator như sau:
#include<iostream>
#include<vector>
using std::vector;
void main()
{
vector<int> v;
for(int i = 10; i < 15; i++) v.push_back(i );
vector<int>::iterator it = v.begin();
while(it != v.end())
{
cout << *it <<" ";
it++;
}
}
Vì iterator định nghĩa bên trong các container – thế nào là “phần tử đầu”, “phần tử cuối”, “phần tử tiếp theo” … nên nó “chứa” thông tin cấu trúc phục vụ cho việc duyệt container. Nó che đi cấu trúc bên trong và cho phép ta viết các đoạn mã tổng quát để duyệt hay chọn phần tử trên các container khác nhau mà không cần biết cấu trúc của container đó ra sao.
Trong các reversible container như vector còn định nghĩa thêm reverse_iterator (cái tên nói lên chức năng: iterator nghịch đảo) là nested class với các “hằng” tương ứng:
**vector<T>::reverse_iterator rbegin();** **vector<T>::reverse_iterator rend();**
Ví dụ : duyệt vector theo 2 chiều
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<vector>
usingnamespace std;
int main()
{
int A[] = {3,2,3,1,2,3,5,3};
int n = sizeof(A)/sizeof(*A);
vector<int> V;
for (int i=0; i<n; i++){
V.push_back(A[i]);
vector<int>::iterator vi;
cout << endl <<"Duyet chieu xuoi"<< endl;
for (vi=V.begin(); vi!=V.end(); vi++)
cout << *vi << endl;
vector<int>::reverse_iterator rvi;
cout << endl <<"Duyet theo chieu nguoc"<< endl;
for (rvi=V.rbegin(); rvi!=V.rend(); rvi++)
cout << *rvi << endl;
getchar();
}
}
Chuyển đổi qua lại giữa reverse_iterator và iterator:
+ Hàm thành viên base(): trả về một iterator trỏ đến phần tử hiện tại của reverse_iterator.
+ Tạo reverse_iterator từ iterator: Contructor reverse_iterator(RandomAccessIterator i);
Ví dụ:
vector<int> v;
vector<int>::iterator it (v.begin());
vector<int>:: reverse_iterator ri(v.rbegin());
//goi contructor
assert(ri.base()==v.end()-1);
ri=v.begin();
//goi contructor
assert(ri.base()==it);
**Lệnh assert(); dùng để kiểm tra một biểu thức điều kiện.* **Iterator**là 1 trong 4 thành phần chính của STL (container, iterator, algorithm và functor).Container và algorithm giao tiếp qua nó: nhiều hàm và algorithm trong STL nhận các đối số là iterator.Iterator gắn liền với tất cả các loại container, đây là khái ni ệm bạn cần nắm rất vững nếu muốn làm việc tốt với STL **Bảng: các hàm thành viên lớp vector**
| |
Hàm thành phần
| |
Mô tả
| |
template<class lnlter>
void assign(lnlter start, lnlter end);
| |
Gán giá trị cho vector theo trình tự từ start đến end.
| |
Template<class Size, class T)
Void assign(Size num, const T &val = T());
| |
Gán giá trị của val cho num phần tử của vector.
| |
Reference at(size_type l);
Const_reference at(size_type l) const;
| |
Trả về một tham chiếu đến một phần tử được chỉ định bởi i.
| |
Reference back(size_type l);
Const_reference at(size_type l) const;
| |
Trả về một tham chiếu đến phần tử cuôi cùng của vector.
| |
Iterator begin();
Const _iterator begin() const;
| |
Trả về một biến lặp chỉ định phần tử đầu tiên của vector.
| |
Size_type capacity() const;
| |
Trả về dung lượng hiện thời của vector. Đây là số lượng các phần tử mà nó có thể chứa trước khi nó cần cấp phát thêm vùng nhớ.
| |
Void clear();
| |
Xóa tất cả các phần tử trong vector.
| |
Bool empty() const;
| |
Trả về true nếu vector rỗng và trả về false nếu ngược lại.
| |
Iterator end();
Const_iterator end() const;
| |
Trả về một biến lặp để kết thúc một vector.
| |
iterator erase(iterator i);
| |
Xóa một phần tử được chỉ bởi i. Trả về một biến lặp chỉ đến phần tử sau phần tử được xóa.
| |
Iterator erase(iterator start, iterator end);
| |
Xóa những phần tử trong dãy từ start đến end. Trả về một biến lặp chỉ đến phần tử sau cùng của vector.
| |
Reference front();
Const_reference front() const;
| |
Trả về một tham chiếu đến phần tử đầu tiên của vector.
| |
Allocator_type get_allocator() const;
| |
Trả về vùng nhớ được cấp phát cho vector.
| |
Iterator insert(iterator I, const T&val=T());
| |
Chèn val trực tiếp vào trước thành phần được chỉ định bởi i. biến lặp chỉ đến phần tử được trả về.
| |
Void insert(iterator I, size_type num, const T&val);
| |
Chèn num val một cách trực tiếp trước phần tử được chỉ định bởi i.
| |
Template<class lnlter>
Void insert(iterator I, lnlter start, lnltr end);
| |
Chèn chuỗi xác định từ start đến end trực tiếp trước một phần tử được chỉ định bởi i.
| |
Size_type max_size() const;
| |
Trả về số lượng phần tử lớn nhất mà vector có thể chứa.
| |
Reference operator[](size_type i) const;
Const_reference operator[] (size_type i) const;
| |
Trả về một tham chiếu đến phần tử được chỉ định bởi i.
| |
Void pop_back();
| |
Xóa phần tử cuối cùng trong vector.
| |
Void push_back(cons T&val);
| |
Thêm vào một phần tử có giá trị val vào cuối của vector.
| |
Reverse_iterator rbegin();
Const_reverse_iterator rbegin() const;
| |
Trả về biến lặp nghịch chỉ điểm kết thúc của vector.
| |
Reverse_iterator rend();
Const_reverse_iterator rend() const;
| |
Trả về một biến lặp nghịch chỉ điểm bắt đầu của vector.
| |
Void reverse (size_type num);
| |
Thiết lập kích thước của vector nhiều nhất là bằng num.
| |
Void resize (size_type num, T val =T());
| |
Chuyển đổi kích thước của vector được xác định bởi num. Nếu như kích thước của vector
tăng lên thì các phần tử có giá trị val sẽ được thêm vào cuối vector.
| |
Size_type size() const;
| |
Trả về số lượng các phần tử hiện thời của trong vector.
| |
Vois swap(vector<T, Allocator>&ob)
| |
Chuyển đổi những phần tử được lưu trong vector hiện thời với những phần tử trong ob.
*VIII.Dùng 1 số hàm cơ bản trong thư viện algorithm* **Khởi tạo:**
Bạn có thể sử dụng lệnh fill của thư viện <algorithm> để tô một vùng giá trị của 1 container (thường là 1 mảng, 1 vector)
// fill algorithm example
#include<iostream>
#include<algorithm>
#include<vector>
usingnamespace std;
void printint(constint&i)
{
cout << i << endl;
}
int main ()
{
vector<int> v(8); // v: 0 0 0 0 0 0 0 0
fill(v.begin(),v.begin()+4,5); // v: 5 5 5 5 0 0 0 0
fill(v.begin()+3,v.end()-2,8); // v: 5 5 5 8 8 8 0 0
cout <<"vector contains:";
for_each( v.begin(), v.end(), printint );
return0;
}
template<classForwardIterator, classGenerator>
void generate(ForwardIterator first, ForwardIterator last, Generator gen);
**Hàm generate**sẽ “sinh” từng phần tử trong khoảng nào đấy của vector bằng cách gọi hàm được chỉ định ( một hàm
trả về cùng kiểu và không có đối số)
Ví dụ với hàm rand():
vector<int> V;
srand( time(NULL) );
//...
generate( V.begin(), V.end(), rand );
**Copy iterator ( tương** **tự** **memcpy() đối với pointer )**
int a[] = {1, 2, 3, 4, 5, 6};
int n = sizeof(a)/sizeof(*a);
vector<int> v1(a, a+n);
vector<int> v2(n);
copy(v1.begin(), v1.end(), v2.begin());
//copy_n(v1.begin(), v1.size(), v2.begin());
for (int i =0; i <n; i++)
cout << v2[i] <<" ";
// The output is "1 2 3 4 5 6".
**Đảo ngược (reverse) vector**
Bạn có thể sử dụng lệnh reverse trong <algorithm> để đảo ngược container (ở đây là 1 vector)
// reverse algorithm example
#include<iostream>
#include<algorithm>
#include<vector> tr.nh C++ Nguyễn Phú Quảng
#include<conio.h>
usingnamespace std;
int main ()
{
vector<int> a;
// set some values:
for (int i=1; i<10; ++i) a.push_back(i); // 1 2 3 4 5 6 7 8 9
reverse(a.begin(),a.end()); // 9 8 7 6 5 4 3 2 1
// print out content:
cout <<"a contains:";
int i, n = a.size();
for (i=0; i<n; i++)
cout << a[i] <<" ";
cout << endl;
getchar();
}
**Thay thế các giá trị (replace)**
Lệnh
**replace**tìm kiếm 1 giá trị trong container, ở đây là vector thay thế giá trị tìm được bởi giá trị mới.
// replace algorithm example
#include<iostream>
#include<algorithm>
#include<vector>
#include<conio.h>
usingnamespace std;
int main ()
{
int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };
vector<int> a (myints, myints+8); // 10 20 30 30 20 10 10 20
replace(a.begin(), a.end(), 20, 99); // 10 99 30 30 99 10 10 99
cout <<"a contains: ";
int i, n;
for (i=0, n=a.size(); i<n; i++)
cout << a[i] <<" ";
getchar();
}
**Thay thế các giá trị theo điều kiện (replace_if)**
Các hàm có hậu tố _if như remove_if, replace_if, find_if, count_if … sử dụng 1 con trỏ hàm hoặc 1 functor để làm tiêu chí tìm kiếm (dạng của con trỏ hàm hoặc functor tùy vào mục đích sử dụng)
Lệnh
**replace_if**cho phép tìm giá trị theo điều kiện do một hàm trả về. Để sử dụng lệnh này bạn phải khai báo 1 hàm có giá trị trả về là bool nhận tham số là giá tr ị của 1 element. Khi hàm trả về true, giá trị tương ứng sẽ bị thay thế bởi giá trị mới. Hàm ki ểm tra nên khai báo inline để tốc độ nhanh hơn.
// replace_if example
#include<iostream>
#include<algorithm>
#include<vector>
#include<conio.h>
usingnamespace std;
inlinebool SoLe(int i) { return ((i%2)==1); }
int main ()
{
vector<int> a;
// set some values:
for (int i=1; i<10; i++) a.push_back(i); // 1 2 3 4 5 6 7 8 9
replace_if(a.begin(), a.end(), SoLe, 0); // 0 2 0 4 0 6 0 8 0
cout <<"a contains: ";
int i, n;
for (i=0, n=a.size(); i<n; i++)
cout << a[i] <<" ";
getchar();
}
**Xóa với remove và remove_if**
Ví dụ 1:
//remove
int A[] = {3,1,4,1,5,9};
int N = sizeof(A)/sizeof(*A);
vector<int> V(A, A+N);
copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
//The output is "3 1 4 1 5 9".
cout << endl;
vector<int>::iterator new_end =
remove(V.begin(), V.end(), 1);
V.resize(new_end - V.begin());
copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
// The output is "3 4 5 9".
Ví dụ 2:
#include<iostream>
#include<algorithm>
#include<vector>
usingnamespace std;
bool IsOdd(int x){
return x%2;
}
int main()
{
int a[] = {3,1,4, 8, 5, 2, 9};
int n = sizeof(a)/sizeof(*a);
vector<int> vec(a, a+n);
vector<int>::iterator new_end =
remove_if( vec.begin(), vec.end(), IsOdd );
vec.erase(new_end, vec.end());
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
// The output is "4 8 2".
return 0;
}
**Các hàm có hậu tố _copy như remove_copy, remove_if_copy, replace_copy, replace_if_copy, reverse_copy sử dụng tương tự nhưng tạo ra và thao tác trên bản sao container** **Sắp xếp container (ở đây là vector)**
#include<iostream>
#include<algorithm>
#include<vector>
usingnamespace std;
void printint(constint&i)
{
cout << i << endl;
}
int main()
{
int A[] = {3,2,3,1,2,3,5,3};
int n = sizeof(A)/sizeof(*A);
vector<int> V(A, A+n);
cout << endl <<"Danh sach ban dau"<< endl;
for_each( V.begin(), V.end(), printint );
V.sort();
vector<int>::iterator vi;
cout << endl <<"Danh sach sau khi sap xep"<< endl;
for_each( V.begin(), V.end(), printint );
getchar();
}
Trong ví dụ trên ta học được cách sử dụng hàm for_each() và sort() để thao tác với 1 container.
**Tìm kiếm tuyến tính**
// lineal search
#include<iostream.h>
#include<algorithm>
#include<vector>
usingnamespace std;
bool IsOdd(int x)
{
return x%2;
}
int main()
{
int a[] = {2,4,2,6,9,1,2,3,2,3,4,5,6,4,3,2,1};
int n = sizeof(a)/sizeof(*a);
vector<int> v(a, a+n);
int first = find(a, a+n, 1) - a;
//các hàm thuật toán hoàn toàn có thể thao tác trên mảng & con trỏ thường
cout <<"[array] so thu tu cua phan tu dau tien = 1: "<< first << endl;
first = find(v.begin(),v.end(), 1) - v.begin();
cout <<"[vector] so thu tu cua phan tu dau tien = 1: "<< first << endl;
//find_if
vector<int>::iterator it;
it = find_if(v.begin(),v.end(), IsOdd );
first = it - v.begin();
cout <<"Phan tu le dau tien la "<< *it <<" o vi tri thu "<< first << endl;
return 0;
}
Ngoài ra còn có nhiều hàm tìm kiếm khác: hàm search() dùng để so khớp 1 chuối liên tiếp các phần tử cho trước, hàm search_n tìm kiếm với số lần lặp xác định, hàm find_end tìm kết quả cuối cùng, find_first_not_of(), find_last_not_of() …
**Đếm & tìm min max**
//counting
#include<iostream>
#include<vector>
#include<algorithm>
usingnamespace std;
bool IsOdd(int x)
{
return x%2;
}
int main()
{
int a[] = {3,2,3,1,2,4,5,3};
int n = sizeof(a)/sizeof(*a);
vector<int> v(a, a+n);
cout <<"So luong so 3 trong mang: "<< count(v.begin(),v.end(), 3) << endl;
cout <<"So luong so le trong mang: "<< count_if(v.begin(),v.end(), IsOdd) << endl;
cout <<"So nho nhat trong mang: "<< *min_element(v.begin(),v.end()) << endl;
cout <<"So lon nhat trong mang: "<< *max_element(v.begin(),v.end()) << endl;;
return 0;
}
**Hàm chuyển đổi hàng lo ạt transform()**
Một trong những giải thuật thú vị hơn là transform(), phần tử được sửa đổi từng cái trong một phạm vi theo một chức năng mà bạn cung cấp.
#include<vector>
#include<algorithm>
usingnamespace std;
template<class T>
T inc(T x )
//hàm dùng để chuyển đổi
{
return x+1;
}
int main()
{
int a[] = {3,2,3,1,2,3,5,3};
int n = sizeof(a)/sizeof(*a);
vector<int> v(a, a+n);
transform(v.begin(), v.end(), v.begin(), inc<int> );
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
// The output is "4 3 4 2 3 4 6 4".
return 0;
}
**Ngoài ra còn nhiều hàm thuật toán khác có thể tham khảo trong tài liệu reference của c++**
Đăng ký:


markdown:
Ngày 20/1, Cơ quan CSĐT Công an TP Hà Nội cho biết, đã tiến hành khởi tố vụ án, khởi tố bị can, bắt tạm giam 2 đối tượng Wiliam Rafael Agular Villanueva (43 tuổi) và Jose Marcelino Velasquez Aviles (63 tuổi) đều mang quốc tịch Peru về tội trộm cắp tài sản.
**Đọc thêm »**

WARC-Type: response

Content-Type: application/http; msgtype=response

WARC-Truncated: length

WARC-Identified-Payload-Type: application/xhtml+xml

Server: cloudflare

Connection: close

Set-Cookie: __cfduid=d5f3b0a1a0b14b5eac1d2ed31fcf8928a1521539180; expires=Wed, 20-Mar-19 09:46:20 GMT; path=/; domain=.tintuc.com; HttpOnly

Vary: Cookie,Accept-Encoding

Content-Type: text/html; charset=UTF-8


markdown:
Theo nhận định của Trung tâm Dự báo Khí tượng Thủy văn Trung ương, nửa cuối tháng một và tháng hai vẫn là các tháng chính của mùa đông, do vậy không khí lạnh vẫn hoạt động với cường độ khá mạnh. Tuy nhiên nền nhiệt độ trung bình các tháng tới...
**Đọc thêm »**

Set-Cookie: __cfduid=d072ff2b5b726596f0ba285871e9e7dd41521539244; expires=Wed, 20-Mar-19 09:47:24 GMT; path=/; domain=.tintuc.com; HttpOnly


markdown:
Á hậu Hoàng Yến, Hoa hậu Kim Hồng... từng gặp tỷ phú Mỹ trước khi ông trở thành tổng thống.
**Đọc thêm »**
### Tin mới nhất
[Tình yêu - Giới tính](http://www.tintuc.com/tinh-yeu-gioi-tinh/)
-
[Đi qua vội vã](http://www.tintuc.com/di-qua-voi-va/)
Jul 24th, 2015 ·
[0 Comment](http://www.tintuc.com/di-qua-voi-va/#respond)
(Dân trí) – Tôi thường có thói quen ngồi một mình nơi góc quán...
-
[Để không gian nhỏ trở nên thoáng rộng hơn](http://www.tintuc.com/de-khong-gian-nho-tro-nen-thoang-rong-hon/)
Jul 24th, 2015 ·
[0 Comment](http://www.tintuc.com/de-khong-gian-nho-tro-nen-thoang-rong-hon/#respond)
(Dân trí) – Bạn sống trong không gian khá chật chội và luôn cảm...
-
[Cô bé 3 tuổi hút 15.000 fan Instagram nhờ phong cách thời trang](http://www.tintuc.com/co-be-3-tuoi-hut-15000-fan-instagram-nho-phong-cach-thoi-trang/)
Jul 24th, 2015 ·
[0 Comment](http://www.tintuc.com/co-be-3-tuoi-hut-15000-fan-instagram-nho-phong-cach-thoi-trang/#respond)
(Dân trí) – Cô bé India Blanshard sống tại miền tây Kirby, Merseyside...
-
[Con chồng](http://www.tintuc.com/con-chong/)
Jul 24th, 2015 ·
[0 Comment](http://www.tintuc.com/con-chong/#respond)
(Dân trí) – Vợ mất được vài năm, thì ông nhà tôi lấy tôi,...
-
[9 quy tắc khi tranh cãi với vợ](http://www.tintuc.com/9-quy-tac-khi-tranh-cai-voi-vo/)
Jul 23rd, 2015 ·
[0 Comment](http://www.tintuc.com/9-quy-tac-khi-tranh-cai-voi-vo/#respond)
Cặp vợ chồng nào cũng có lúc cãi nhau. Vấn đề là làm sao để...

Set-Cookie: __cfduid=dbd948ca7efa0aa98af09edc5d0f74ec11521539259; expires=Wed, 20-Mar-19 09:47:39 GMT; path=/; domain=.tintuc.com; HttpOnly


markdown:
Ông Nguyễn Khiêm, Chánh văn phòng UBND TP Cam Ranh Hòa xác nhận: "Từ huyện Di Linh (Lâm Đồng) xuống TP Cam Ranh chơi và tắm biển, 3 cô gái đã bị đuối nước, một người bị mất tích ở Bãi Dài, phía sau Cảng hàng không quốc tế Cam Ranh (phường Cam...
**Đọc thêm »**

Set-Cookie: __cfduid=d317ffff051cebfe3468624fc74e059db1521539290; expires=Wed, 20-Mar-19 09:48:10 GMT; path=/; domain=.tintuc.com; HttpOnly


markdown:
Hai tháng đầu năm 2015, Việt Nam nhập khẩu ôtô nguyên chiếc nhiều nhất từ Ấn Độ. Ảnh minh họa: Hyundai. Theo Tổng cục Hải quan, lượng ôtô nguyên chiếc các loại nhập khẩu trong 2 tháng đầu năm nay đạt gần 15.100 xe với tổng trị giá...
**Đọc thêm »**
Hai tháng đầu năm 2015, Việt Nam nhập khẩu ôtô nguyên chiếc nhiều nhất từ Ấn Độ. Ảnh minh họa: Hyundai. Theo Tổng cục Hải quan, lượng ôtô nguyên chiếc các loại nhập khẩu trong 2 tháng đầu năm nay đạt gần 15.100 xe với tổng trị giá...
**Đọc thêm »**
© 8838
[Tin Tức](http://www.tintuc.com). All rights reserved. [WordPress Theme](http://www.theme-junkie.com) designed by [Theme Junkie](http://www.theme-junkie.com)

Set-Cookie: __cfduid=de2a42fd475a07b07222c3557470ae6e01521539196; expires=Wed, 20-Mar-19 09:46:36 GMT; path=/; domain=.tintuc.com; HttpOnly


markdown:
Trang chủ
Sản phẩm
Hot Deals
Tra cứu D.Vụ
Bảng giá
Khuyến mãi
Dịch vụ
Hỗ trợ
Tin tức - Sự kiện
Tuyển dụng
Liên hệ
Đăng ký
|
Đăng nhập
Mua hàng online
Kinh Doanh TNC_1
Kinh Doanh TNC_2
Kinh Doanh TNC_3
Kinh Doanh TNC_4
Kinh Doanh TNC_5
Kinh Doanh TNC_6
SỬA ĐIỆN THOẠI
Laptop :
(028) 39 252 529
Sales 1 :
39 250 259 - 14
Sales 2 :
39 250 259 - 30
Sales 3 :
39 250 259 - 31
Sales 4 :
39 250 259 - 32
Trả góp :
1900 6078 - 19
Giỏ hàng (0)
Linh Phụ Kiện
Thương hiệu
Danh mục con
Mouse
Keyboard
Mouse + Keyboard Combo
Sản phẩm Game
Tai Nghe - Micro
Sản phẩm khác
Loa
USB
Game Pad
Thẻ Nhớ
Sạc dự phòng
Ổ cắm điện
Dây Cable sạc/ Cable chuyển đổi
HUB USB - Reader
CARD PCI & Bộ chuyển đổi
HDD Box & Bàn Vẽ
Linh phụ kiện điện thoại
Bộ dụng cụ sửa máy vi tính
Mức giá
Dưới 5 triệu
5 triệu đến 9 triệu
9 triệu đến 12 triệu
12 triệu đến 14 triệu
Trên 14 triệu
Laptop
Thương hiệu
Mức giá
Dưới 5 triệu
5 triệu đến 9 triệu
9 triệu đến 12 triệu
12 triệu đến 14 triệu
Trên 14 triệu
PC - Server
Thương hiệu
Mức giá
Dưới 5 triệu
5 triệu đến 9 triệu
9 triệu đến 12 triệu
12 triệu đến 14 triệu
Trên 14 triệu
Màn Hình LCD
Thương hiệu
Danh mục con
Màn hình 15.6" - 17"
Màn hình 18.5" - 21.0"
Màn hình 21.5" trở lên
Mức giá
Dưới 5 triệu
5 triệu đến 9 triệu
9 triệu đến 12 triệu
12 triệu đến 14 triệu
Trên 14 triệu
Linh Kiện PC
Thương hiệu
Danh mục con
Mainboard
CPU
Ram
HDD
VGA Card
DVD
Case
Power
Sound Card
Mức giá
Dưới 5 triệu
5 triệu đến 9 triệu
9 triệu đến 12 triệu
12 triệu đến 14 triệu
Trên 14 triệu
LK - Laptop
Thương hiệu
Danh mục con
Ram Laptop
SSD Laptop
HDD Laptop
Keyboard Laptop
Pin Laptop
Adapter Laptop
Pin Laptop - Hàng chính hãng
Màn hình Laptop
Mức giá
Dưới 5 triệu
5 triệu đến 9 triệu
9 triệu đến 12 triệu
12 triệu đến 14 triệu
Trên 14 triệu
HDD External
Thương hiệu
Mức giá
Dưới 5 triệu
5 triệu đến 9 triệu
9 triệu đến 12 triệu
12 triệu đến 14 triệu
Trên 14 triệu
Thiết Bị Mạng
Thương hiệu
Danh mục con
Wireless
Network Card Wireless & USB Wireless
ADSL & ADSL Wireless Router
USB 3G & 3G/4G Mobile Wi-Fi
Hub-Switch
Cable Mạng
Mức giá
Dưới 5 triệu
5 triệu đến 9 triệu
9 triệu đến 12 triệu
12 triệu đến 14 triệu
Trên 14 triệu
T.Bị Văn Phòng
Thương hiệu
Danh mục con
Máy in
Mực in
UPS
Máy Scan
Máy Fax
Máy hủy tài liệu
Máy quét mã vạch
Máy đếm tiền
Máy chấm công
Máy chiếu
Màn chiếu
Mức giá
Dưới 5 triệu
5 triệu đến 9 triệu
9 triệu đến 12 triệu
12 triệu đến 14 triệu
Trên 14 triệu
Camera
Thương hiệu
Danh mục con
D-Link
Vivotek
Logitech
TENDA
iThink
Mức giá
Dưới 5 triệu
5 triệu đến 9 triệu
9 triệu đến 12 triệu
12 triệu đến 14 triệu
Trên 14 triệu
Phần Mềm
Thương hiệu
Danh mục con
Phần Mềm Diệt Virus
Phần Mềm Microsoft
Mức giá
Dưới 5 triệu
5 triệu đến 9 triệu
9 triệu đến 12 triệu
12 triệu đến 14 triệu
Trên 14 triệu
Thiết bị gia dụng
Thương hiệu
Danh mục con
Smart Robot
Máy Lọc Không Khí
Đèn Pin - Đèn Bàn
Dao, kéo đa năng
Kìm bấm
Mức giá
Dưới 5 triệu
5 triệu đến 9 triệu
9 triệu đến 12 triệu
12 triệu đến 14 triệu
Trên 14 triệu
ĐT - thiết bị KTS
Thương hiệu
Danh mục con
Điện thoại bàn
T.Bị Kỹ Thuật Số
Hộp truyền hình internet
Mức giá
Dưới 5 triệu
5 triệu đến 9 triệu
9 triệu đến 12 triệu
12 triệu đến 14 triệu
Trên 14 triệu
Trang chủ
Sản phẩm
APPLE
ĐT - thiết bị KTS
Điện thoại bàn
T.Bị Kỹ Thuật Số
Thẻ cào điện thoại
Hộp truyền hình internet
Thương hiệu
APPLE
SONY
SAMSUNG
PANASONIC
ELECOM
Khác
PISEN
BUFFALO
VERBATIM
APACER
WOPOW
KASHIMURA
CANON
PQI
TEAM
ENERGIZER
Techmate
REMAX
RAVPOWER
Danel
ROMOSS
PHILIPS
ADATA
RAPOO
Zadez
VIETTEL
MOBIFONE
VINAPHONE
Cheero
ORICO
Ugreen
ROBOTEK
Giá bán
Dưới 5 triệu
5 triệu đến 9 triệu
9 triệu đến 12 triệu
12 triệu đến 14 triệu
Trên 14 triệu
APPLE
Hiện không có sản phẩm nào
TNC Khuyến mãi mỗi ngày
Thông tin công ty
Giới thiệu công ty
Hoạt động
Cơ cấu bộ phận kinh doanh
Bản quyền & Sở hữu
Hướng dẫn khách hàng
Hướng dẫn đặt hàng
Hướng dẫn thanh toán
Hỗ trợ đặt hàng
Tình trạng đơn hàng
Thắc mắc - Góp ý
HỖ TRỢ KỸ THUẬT
Tư vấn hỏi đáp kỹ thuật
Download
Chính sách công ty
C.Sách đổi trả hàng
Chính sách bảo hành
Chính sách thành viên
C.Sách bảo mật T.Tin
Thông tin website
Sơ đồ website
Đường đến công ty
Hợp tác, trao đổi
Đăng ký nhận tin
Giới tính
Nam
Nữ
Chấp nhận thanh toán trực tuyến qua:
Follow us on: :
Copyright © 2012
Công ty TNHH Tin Học Thành Nhân
Thiết kế web chuyên nghiệp:
TRUST.vn

WARC-Identified-Payload-Type: text/html

P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"

Vary: Accept-Encoding,User-Agent

Content-Type: text/html


markdown:
Chương trình
Đây là chương trình khuyến mãi thẻ nạp không chỉ có ưu đãi khủng mà còn có thời gian triển khai dài ngày giúp người dùng có thể thoải mái bổ sung tài khoản kếch xù.
Nếu quý khách hàng quan tâm đến chương trình
**dành tặng quý khách hàng đang sử dụng thuê bao trả trước** [khuyến mãi 50% giá trị thẻ nạp Viettel từ ngày 12/9 - 30/9/2017](http://www.tongdaiviettel.info/2017/09/viettel-khuyen-mai-50-the-nap-tu-ngay-129-3092017.html) [Viettel](http://www.tongdaiviettel.info/)trên toàn quốc ưu đãi lên đến 50% giá trị thẻ nạp, áp dụng đối với tất cả các hình thức nạp thẻ hiện hành của nhà mạng.
Đây là chương trình khuyến mãi thẻ nạp không chỉ có ưu đãi khủng mà còn có thời gian triển khai dài ngày giúp người dùng có thể thoải mái bổ sung tài khoản kếch xù.
**Viettel khuyến mãi 50% thẻ nạp từ ngày 12/9 - 30/9**là cơ hội tuyệt vời để quý khách hàng Viettel bổ sung tài khoản với chi phí tiết kiệm nhất, từ đó có thể thoải mái gọi thoại, nhắn tin, truy cập Internet từ nay đến hết tháng 9.
Nếu quý khách hàng quan tâm đến chương trình
[khuyến mãi nạp thẻ Viettel](http://www.tongdaiviettel.info/search/label/Khuy%E1%BA%BFn%20m%C3%A3i%20Viettel)lần này, hãy dành thời gian theo dõi bài viết này nhé!
##
**Nội dung CT Viettel khuyến mãi thẻ nạp từ ngày 12/9 - 30/9:**
Nhà mạng Viettel đưa ra những quy định cụ thể về đối tượng, thời gian khuyến mãi và phạm vi áp dụng cho chương trình khuyến mãi từ ngày 12/9 - 30/9 cụ thể như sau:
- Đối tượng tham gia: Chương trình khuyến mãi lần này áp dụng đối với các thuê bao trả trước mạng Viettel nhận được tin nhắn mời tham gia nạp thẻ nhận khuyến mãi từ nhà mạng Viettel đáp ứng điều kiện vào thời điểm nạp thẻ, số dư tài khoản chính của quý khách hàng phải nhỏ hơn hoặc bằng 3.000đ
- Phạm vi áp dụng: Áp dụng rộng rãi trên toàn quốc.
- Thời gian triển khai khuyến: Từ 0h00’ ngày 12/9/2017 đến 23h59 phút ngày 30/9/2017.
- Hình thức nạp thẻ nhận ưu đãi: Áp dụng đối với tất cả các hình thức nạp thẻ hiện hành của nhà mạng Viettel.
###
**Ưu đãi khủng từ khuyến mãi thẻ nạp 12/9 - 30/9 mạng Viettel:**
Hơn nửa tháng 9 còn lại, khách hàng Viettel nằm trong đối tượng tham gia khuyến mãi sẽ không còn phải lo lắng chi phí nạp thẻ nữa, bởi khi tham gia nap thẻ vào bất kỳ ngày, với mệnh giá tùy thích cũng đều
**nhận được ưu đãi cực khủng lên đến 50% giá trị thẻ nạp**. Nhà mạng Viettel đã chia mức ưu đãi cụ thể cho các đối tượng khác hàng như sau:
- Đối với các thuê bao đang sử dụng gói TOMS, TOM690, SV690, TSV2017 khi nạp thẻ thành công sẽ nhận được 50% giá trị thẻ nạp vào tài khoản khuyến mãi nội mạng.
- Các thuê bao Homphone trả trước của Viettel sẽ nhận được ưu đãi 50% vào tài khoản.
- Các thuê bao còn lại mạng Viettel được tặng 50% giá trị thẻ nạp vào tài khoản khuyến mãi với 25% cộng vào tài khoản sử dụng nội mạng và 25% cộng vào tài khoản sử dụng liên mạng.
- Quý khách hàng có thể thoải mái nạp thẻ bởi khuyến mãi lần này không giới hạn số lần nạp thẻ.
Sau khi tham gia nạp thẻ vào
Đối với quý khách hàng thường xuyên sử dụng Internet để học tập, làm việc, giải trí thì đừng quên đăng ký cho mình
- Soạn: 4G90 0987912184 gửi 9123
- Chỉ với 90.000đ quý khách hàng sở hữu ngay gói 4G90 với tốc độ truy cập cực đỉnh, hứa hẹn sẽ mang đến những trải nghiệm tuyệt vời cho khách hàng.
**chương trình khuyến mãi thẻ nạp Viettel trong các ngày 12/9 đến 30/9**quý khách hàng sẽ sở hữu tài khoản chính và tài khoản khuyến mãi khổng lồ, quý khách hàng có thể thoải mái gọi thoại, nhắn tin hay [đăng ký 3G Viettel](http://www.tongdaiviettel.info/2015/08/cach-dang-ky-3g-viettel.html), [4G Viettel](https://4gvietteltelecom.vn/dang-ky-4g-viettel.html)truy cập Internet mọi lúc mọi nơi.
Đối với quý khách hàng thường xuyên sử dụng Internet để học tập, làm việc, giải trí thì đừng quên đăng ký cho mình
[gói cước 4G90 Viettel](https://4gvietteltelecom.vn/dang-ky-goi-4g90-viettel.html)với cú pháp sau để nhận ngay ưu đãi 3GB sử dụng trong thười gian 30 ngày nếu là thuê bao trả trước và chu kỳ tháng nếu là thuê bao trả sau.
- Soạn: 4G90 0987912184 gửi 9123
- Chỉ với 90.000đ quý khách hàng sở hữu ngay gói 4G90 với tốc độ truy cập cực đỉnh, hứa hẹn sẽ mang đến những trải nghiệm tuyệt vời cho khách hàng.
**Viettel khuyến mãi 50% thẻ nạp từ 12/9-30/9**mang đến cho người dùng mạng Viettel cơ hội bổ sung tài khoản với chi phí tiết kiệm từ đó tha hồ sử dụng dịch vụ gọi thoại, nhắn tin, [đăng ký các gói cước 4G Viettel](http://www.tongdaiviettel.info/2016/11/dang-ky-cac-goi-cuoc-4g-viettel.html)theo nhu cầu.

Server: GSE

X-Content-Type-Options: nosniff

Cache-Control: private, max-age=0

X-XSS-Protection: 1; mode=block


markdown:
|
|
![]()
|
|![]()
Người Sài Gòn bì bõm trong nước dù trời không mưa
|
||
|![]()
Post
|
|
Dzịt Tốt Tướng
![]()
![]()
![]()
![]()
![]()
![]()
![]()
Group: Active Members
Posts: 1,902
Joined: 16-June 07
Member No.: 59,901
![]()
|
|
Người Sài Gòn bì bõm trong nước dù trời không mưa
Triều cường 1,6 m - cao nhất trong năm - khiến nước sông, kênh rạch tràn bờ, gây ngập nhiều khu vực ở TP HCM.
Chiều 28/10, triều cường lên cao khiến nước từ kênh Thanh Đa vượt bờ kè, tràn vào hàng nghìn nhà dân ở quận Bình Thạnh. Điểm duy nhất có thể phân biệt giữa kênh và đường là bờ rào bằng sắt.
Ông Nguyễn Văn Mau sống ngay bờ kênh cho biết, nước bắt đầu lên lúc 17h, nhiều chỗ ngập đến 0,5 m. "Triều lên phải 3-4 tiếng sau mới rút. Khu này không mưa nhưng cứ đến hẹn lại ngập nặng vậy đấy", ông này nói.
Nước có mùi hôi thối, thường gây ngứa nên ông Mau và bạn nhậu phải để chân vào thùng nhựa, tránh tiếp xúc nước.
Những quán cà phê dọc bờ kênh nước ngập mênh mông khiến việc buôn bán ế ẩm. Chủ quán thẫn thờ ngồi chờ khách. Còn trong các con hẻm nước ngập sâu hơn, rất ít người ra đường.
Bà Phạm Thị Trân sống tại đây hơn 30 năm biết thuỷ triều sẽ lên cao nên ăn cơm từ sớm. Bà cũng mang ủng sẵn để tiện đi lại. "Sống vầy quen rồi, đến ngày triều lên thì mọi thứ phải sẵn sàng. Tui cũng tránh ra ngoài bởi bùn đất trơn trướt. Lúc nãy lội nước té bầm tím chân", cụ bà hơn 70 tuổi cho biết.
Đa phần người dân phải ngồi xổm trên ghế, đồ đạc, giày dép được gói ghém để lên cao tránh bị nước đẩy đi mất.
Tủ lạnh được kê trên đá.
Mọi vật dụng ngập trong triều cường.
Không chỉ Thanh Đa, nhiều khu vực khác ở TP HCM cũng rơi vào tình trạng ngập nặng do triều cường lên cao như quận 2, 8, Nhà Bè...
Theo Đài khí tượng thủy văn khu vực Nam Bộ, hôm nay triều cường đạt đỉnh. Mực nước đo được tại trạm Phú An trên sông Sài Gòn ở mức 1,61 m. Tuy không có mưa nhưng những khu vực trũng, thấp đều chìm trong nước. Dự báo, triều cường sẽ giảm trong vài ngày tới.
Theo các chuyên gia, với tốc độ đô thị hóa nhanh cùng việc lấn chiếm kênh rạch, san lấp như hiện nay, mực nước sông Sài Gòn năm sau luôn cao hơn năm trước nếu TP HCM không có giải pháp khắc phục hiệu quả. Mức triều cường kỷ lục từng xảy ra là 1,68 m ở sông Sài Gòn năm 2013 và 2014, còn trên sông Đồng Điền là 1,7 m vào tháng 11/2014.
Nước thối tấn công nhà dân khi triều cường đạt đỉnh.
|
||
|![]()
Post
|
|
Dzịt Tốt Tướng
![]()
![]()
![]()
![]()
![]()
![]()
![]()
Group: Active Members
Posts: 1,902
Joined: 16-June 07
Member No.: 59,901
![]()
|
|
Ý kiến bạn đọc (42)
Mới nhất | Quan tâm nhất
Đàn vịt nhà tôi rất thích bơi/
Triều cường lên cao nước ngập rồi/
Ngụp lặn trong sân chưa thấy đã/
Vào nhà, vịt tổ chức thi bơi/
Này con vịt sám bơi nhanh quá/
Vịt đen, vịt trắng đuổi tới nơi/
Bì bõm trong nhà cùng lũ vịt/
Trọng tài là tôi cũng thấy vui!
Duy Tuấn - 21:32 28/10
Trả lời | Thích 583 | Vi phạm | Chia sẻ
Ha ha, hay và hài quá, đúng là Thánh thơ!
Tễu - 21:51 28/10
Trả lời | Thích 40 | Vi phạm | Chia sẻ
Nuoc da len the day!!
Dung Tran - 00:39 29/10
Trả lời | Thích 18 | Vi phạm | Chia sẻ
Xem tất cả 7 trả lời
Thanh Đa nước lại tràn bờ
Em tôi bó gối ngồi chờ nước qua
Mơ màng tầm mắt xa xa
Tưởng chừng nước lũ về qua cánh đồng
Ngồi đây ở giữa phố đông
Nghe từng con sóng bềnh bồng nước trôi
Quả là tội nghiệp em tôi
Nhớ quê nên mãi bồi hồi dấu xưa !
Sông Quê - 21:25 28/10
Trả lời | Thích 397 | Vi phạm | Chia sẻ
Thích thơ Bác quá , lãng mạn , tình cảm ...
David Vu - 02:40 29/10
Trả lời | Thích 18 | Vi phạm | Chia sẻ
like bài thơ của bác
Binh Nguyen - 06:38 29/10
Trả lời | Thích 5 | Vi phạm | Chia sẻ
Nắng mưa là chuyện của trời
Triều cường nước ngập do người mà ra
Lấn kênh lấp rạch xây nhà
Người dân bán đảo Thanh Đa ưu phiền
Bờ kè nước ngập liên miên
Nước tràn đường phố nước len vô nhà
Sài Gòn-Bình Quới đâu xa
Ngày rằm, mười sáu muốn qua thăm nàng
Nhưng vì ngại cảnh nước dâng
Triều cường buổi sáng hẹn nàng buổi trưa.
David Tèo - 21:46 28/10
Trả lời | Thích 209 | Vi phạm | Chia sẻ
xin mạn phép đề nghị đổi thành " nhưng vì ngại cảnh nước tràn..." sẽ vần hơn nhiều...xin cám ơn
mèo ngoan - 23 giờ trước
Trả lời | Thích 30 | Vi phạm | Chia sẻ
Sài Gòn cô tiên năm 2000. Sài Gòn cô ...thủy năm 2015.
nguyễn đức phúc - 22:44 28/10
Trả lời | Thích 79 | Vi phạm | Chia sẻ
Cần chi phải sắm du thuyền
Giường nay cũng sắp thành thuyền còn chi!
Nhưng mà có chút nguy nguy
Nước ngập vòi nước lấy gì nấu cơm!
Anh Le Anh - 21:42 28/10
Trả lời | Thích 71 | Vi phạm | Chia sẻ
Nước không chui vào cống, nước sẽ chảy trên đường; Đường toàn bê tông nước không chỗ để rút; Nhà lầu càng mọc, người cứ tăng, hệ thống cống theo không kịp tỷ lệ; Kênh rạch càng thu hẹp, càng lấp, diện tích chứa nước càng thu hẹp; Tất cả ...
thanhtrinh - 21:22 28/10
Trả lời | Thích 47 | Vi phạm | Chia sẻ
Việc Thanh Đa, quận 2, Nhà Bè ngập là chuyện bao đời nay rồi bạn ơi, không phải do hệ thống cống rãnh gì đâu. Mà do đất ở Sài Gòn thấp, triều cường sông Sài Gòn dâng cao là ngập, có năm Thủ Đức cũng ngập thê thảm luôn.
Hien Le Vinh - 22:18 28/10
Trả lời | Thích 33 | Vi phạm | Chia sẻ
Xem tất cả 3 trả lời
|
|![]()
|
|![]()
![]()
|
|
|
|
|
|nbsp;|

Set-Cookie: modpids=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=vietlove.us

Vary: Accept-Encoding


markdown:
**Những "con sâu làm sầu nồi canh" trong chùm ảnh dưới đây không chỉ làm mất mĩ quan tác phẩm mà còn khiến người xem phát cáu.**
Trong cuộc sống, không ít lần bạn gặp phải những tình huống khiến bạn vô cùng bực tức và khó chịu. Điển hình như việc bạn đến siêu thị mua sắm và phát hiện ra giữa quầy bán
[nước tương](http://www.yan.vn/nuoc-tuong-ban-dang-dung-duoc-lam-nhu-the-nao-69191.html?utm_campaign=InternallinkYAN&utm_source=100271&utm_medium=noniadesktop) xuất hiện một chai nước mắm, hay tình cờ trên con đường dát đầy gạch đỏ. bạn nhận ra có một viên gạch xanh đang nằm lẫn lộn. Tất cả những chi tiết ấy tưởng như nhỏ nhặt nhưng lại gây "ngứa mắt" người nhìn không ít chút nào.
Hãy điểm qua những bức ảnh dưới đây để kiểm tra "mức độ sầu của những con sâu" ấy nhé.
Thật khó để tìm ra "kẻ gây rối" trong bức ảnh.
Bụi cỏ "có duyên" nhất mọi thời đại là đây.
Cây bàn chải này ngã "thật đúng lúc".
Giá như người ghép thảm có thể "tinh mắt" hơn.
Đến
[xúc xích](http://www.yan.vn/su-that-tan-khoc-dang-sau-mon-xuc-xich-thit-xong-khoi-ban-van-an-hang-ngay-81410.html?utm_campaign=InternallinkYAN&utm_source=100271&utm_medium=noniadesktop) cũng cần "thẳng hàng".
Đố bạn tìm ra sự khác biệt trong bức ảnh.
Thiết kể cổng hơi "bất đối xứng" thì phải.
Đề nghị đồng chí heo phía bên phải tập trung hơn.
Chiếc muỗng đen xuất hiện không đúng lúc gì cả.
Ai đã đóng nhầm nắp cống thế này?
Chỉ cần xoay thêm một tí nữa là ngay ngắn rồi.
Sao lại có một khoá tủ cao bất thường vậy nhỉ?
Đề nghị chú gà vàng trở về đúng hàng ngũ ngay nhé.
Khi người tuyết cũng biết "đội nón"
Ước gì cây cột kia đừng xuất hiện để đội hình không bị "rôi".
Đỉnh cao của
[nghệ thuật](http://www.yan.vn/tro-mat-voi-nghe-thuat-body-painting-day-me-hoac-v-76881.html?utm_campaign=InternallinkYAN&utm_source=100271&utm_medium=noniadesktop) xếp bánh là đây.
Có điều gây "hoang mang" trong bức ảnh.
Phải chăm chút cẩn thận cho công trình của mình chứ.
Ai mà xếp viên gạch "có tâm" thế.
Chỗ người ta ăn mà cũng bắt bẻ nữa.
Vị trí của viên kẹo xanh có vẻ "sai".
Chỗ cần thì thiếu, chỗ muốn thiếu lại dư.
Đến cả những chiếc cốc cũng làm người xem "tức mắt".
Ô
[cửa sổ](http://www.yan.vn/vi-sao-phai-mo-man-cua-so-khi-may-bay-cat-canh-va-ha-canh-87489.html?utm_campaign=InternallinkYAN&utm_source=100271&utm_medium=noniadesktop) được bố trí do "vô ý" hay "cố tình" nhỉ?
Có ai để ý thấy vật gì màu đỏ đỏ không nhỉ?
Chỉ nhìn chiếc ghế thôi là "hết muốn ngồi".
Những chiếc hộp trông thật "mất trất tự".
Có một kẻ gây rối trong bức ảnh..
Chắc người thợ sửa cống vội quá nên xoay nhầm nắp.
Giá như tuyết có thể lắp đầy các ô.
Những "kẻ gây rối" luôn xuất hiện mọi lúc mọi nơi các bạn nhỉ. Hãy luôn để ý chăm chút và cẩn thận với các tác phẩm của mình để chúng được
[hoàn hảo](http://www.yan.vn/7-dau-hieu-cua-mot-co-ban-gai-hoan-hao-73191.html?utm_campaign=InternallinkYAN&utm_source=100271&utm_medium=noniadesktop) nhất có thể nhé.
(Ảnh: Internet )

Server: nginx

Content-Type: text/html; charset=utf-8