1. Trang chủ
  2. » Cao đẳng - Đại học

Kỹ thuật lập trình | Tài liệu, cơ sở ngành CNTT

98 7 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 98
Dung lượng 915,22 KB

Nội dung

▹ Con trỏ nhanh: khởi tạo trỏ vào phần tử đầu danh sách (Head), mỗi lần lặp sẽ di chuyển sang phần tử kế tiếp của phần tử tiếp theo (2 bước). ▫ Nếu sau một số lần lặp hữu hạn mà cả ha[r]

(1)(2)

Ví dụ

char *pchar; short *pshort; long *plong; pchar ++; pshort ++; plong ++;

Giả sử địa ban đầu tương ứng trỏ 100, 200 300, kết ta có giá trị 101, 202 304 tương ứng

Nếu viết tiếp

plong += 5; => plong = 324 pchar -=10; => pchar = 91 pshort +=5; => pshort = 212

(3)

Ví dụ char *a;short *b; long *c;

Các trỏ a, b, c trỏ tới ô nhớ 1000, 2000 3000

(4)

Chú ý

++ có độ ưu tiên cao * nên *p++

tương đương với *(p++) tức tăng địa mà nó trỏ tới khơng phải tăng giá trị mà chứa.

*p++ = *q++ sẽ tương đương với *p = *q;

p=p+1; q=q+1;

(5)

Ví dụ:

#include <iostream.h> #include<conio.h>

void main () {

int a = 20, b = 15, *pa, *pb, temp;

pa = &a; // trỏ pa chứa địa a pb = &b; // trỏ pb chứa địa b temp = *pa;

*pa = *pb; *pb = temp;

cout << "a = " << a << endl; cout << “b = ” << b;

}

// kết xuất màn hình

(6)

Con trỏ mảng

• Truy cập phần tử mảng trỏ

6

Kiểu mảng Kiểu trỏ

&<Tên mảng>[0] <Tên trỏ > &<Tên mảng> [<Vị

trí>] <Tên trỏ> + <Vị trí> <Tên mảng>[<Vị

(7)

Ví dụ char ch[10], *p;

p = ch;

• p gán địa phần tử mảng ch p = ch;

• Để tham chiếu phần tử thứ mảng ch, ta dùng cách sau:

• ch[2]

(8)

Ví dụ

#include <iostream.h> #include <conio.h> void main ()

{

int numbers[5], * p;

p = numbers; *p = 10; p++; *p = 20;

p = &numbers[2]; *p = 30; p = numbers + 3; *p = 40; p = numbers; *(p+4) = 50; for (int n=0; n<5; n++)

(9)

Ví dụ Numb ers int Numbers[5]; p= Numbers;

int *p; p

*p = 10;

10

p p++; *p =

20;

20

p =

&numbers[2];

p

*p = 30;

20

p = numbers + 3;

p p

*p = 40;

40

30 50

p

p = numbers; *(p+4) = 50;

(10)

Con trỏ xâu

• Ta có char tinhthanh[30] =“Da Lat”;

• Tương đương :

char *tinhthanh;

tinhthanh=“Da lat”;

Hoặc: char *tinhthanh =“Da lat”;

• Ngồi thao tác xâu tương tự như mảng

*(tinhthanh+3) = “l”

• Chú ý : với xâu thường khơng thể gán trực tiếp dịng thứ 3

(11)

Mảng trỏ

• Một ưu điểm khác mảng trỏ ta hốn chuyển đối tượng (mảng con, cấu trúc ) trỏ trỏ cách hoán đổi trỏ

• Ưu điểm việc truyền tham số hàm

• Ví dụ: Vào danh sách lớp theo họ tên, sau đó xếp để in theo thứ tự ABC.

(12)

Mảng trỏ

(13)

Con trỏ trỏ tới trỏ

Ví dụ: in ma trận vuông cộng phần tử ma trận với 10

(14)

Bài tập

Vi t chế ương trình tính t ng ph n t ổ ầ ử

(15)

int main() {

int numArray[6]; int i, sum = 0;

int *ptr = numArray;

cout << "Nhap phan tu: " << endl; for (i = 0; i < 6; i++)

cin >> *(ptr+i); ptr = numArray;

for (i = 0; i < 6; i++) { sum = sum + *ptr;

ptr++; }

cout << "Tong cac phan tu cua mang la: " << sum << endl; return(0);

(16)

Bài tập

Xây d ng m t hàm tính đ dài c a chu i s ự ộ ộ ủ ỗ ử

(17)

Bài tập

Xây d ng m t hàm tính đ dài c a chu i s d ng ự ộ ộ ủ ỗ ụ

tr ỏ

int string_ln(char*p) /* p=&str[0] */ {

int count = 0;

while (*p != '\0') { count++;

p++; }

(18)

Bài tập

Vi t chế ương trình nh p vào n s nguyên, ậ ố

th c hi n (s d ng tr ):ự ệ ử ụ ỏ

-Tính giá trị trung bình, giá trị max phần tử mảng

(19)

Ví dụ

(20)

Bộ nhớ động cho mảng chiều

20

• Cách 1: Biểu diễn mảng chiều thành mảng chiều • Gọi X mảng hai chiều có kích thước m dòng n

cột A mảng chiều tương ứng,

(21)

Bộ nhớ động cho mảng chiều

21

• Cách 2: Dùng trỏ trỏ

• Ví dụ: Với mảng số ngun chiều có kích thước R * C ta khai báo sau:

int **mt;

mt = new int *[R];

int *temp = new int[R*C]; for (i=0; i< R; ++i) {

mt[i] = temp; temp += C;

}

• Để giải phóng:

(22)

Bộ nhớ động cho mảng chiều

• Ví dụ khác để cấp phát động cho mảng hai chiều chứa các số thực float

(23)

Bài tập

Vi t chế ương trình c ng hai ma tr n v i d li u m i ma tr n ộ ậ ớ ữ ệ ỗ ậ

đượ ấc c p phát b nh đ ng theo hai cách:ộ ớ ộ

1) S d ng ử ụ con trỏ

(24)

Cộng hai ma trận với ma trận cấp phát

động #include <iostream.h> #include <conio.h> int main() { int M,N;

int *A = NULL, *B = NULL, *C = NULL;

cout << "Nhap so dong cua ma tran:"; cin>>M;

cout << "Nhap so cot cua ma tran:"; cin>>N;

//Cấ3p phát vùng nhớ cho ma trận A

if(!AllocMatrix(&A,M,N)) {

cout << "Khong du bo nho! "

<< endl; return 1;

}

//Cấ3p phát vùng nhớ cho ma trận B

if(!AllocMatrix(&B,M,N)) {

(25)

//Cấ3p phát vùng nhớ

//cho ma trận C

if (!

AllocMatrix(&C,M,N)) {

cout << "Khong

du

bo nho!" <<endl;

//Gia@i phóng vùng

nhớ A

FreeMatrix(A);

//Gia@i phóng vùng

nhớ B

FreeMatrix(B);

return 1;

}

cout << "Nhap ma tran

thu 1"<< endl;

InputMatrix(A,M,N,'A');

cout << "Nhap ma tran

thu 2"<<endl;

InputMatrix(B,M,N,'B'); clrscr();

cout<<"Ma tran thu 1"<<endl; DisplayMatrix(A,M,N);

cout<<"Ma tran thu 2"<<endl;

DisplayMatrix(B,M,N); AddMatrix(A,B,C,M,N);

cout <<"Tong hai ma tran "

<<endl;

DisplayMatrix(C,M,N);

//Gia@i phóng vùng nhớ A

FreeMatrix(A);

//Gia@i phóng vùng nhớ B

FreeMatrix(B);

//Gia@i phóng vùng nhớ C

FreeMatrix(C); return 0;

(26)

//Cộng hai ma trận

void AddMatrix(int *A,int *B,int*C,int M,int N) {

for(int I=0;I<M*N;++I) C[I] = A[I] + B[I];

}

//Cấ3p phát vùng nhớ cho ma trận

int AllocMatrix(int **A,int M,int N) {

*A = new int [M*N]; if (*A == NULL)

return 0; return 1; }

//Gia@i phóng vùng nhớ

void FreeMatrix(int *A) {

(27)

//Nhập giá trị cu@a ma trận

void InputMatrix(int *A,int M,int N,char Symbol) { for(int I=0;I<M;++I) for(int J=0;J<N;++J) { cout<<Symbol<<"["<<I<<"]["<<J<<"]="; cin>>A[I*N+J]; } }

//Hiể@n thị ma trận

void DisplayMatrix(int *A,int M,int N) {

for(int I=0;I<M;++I) {

for(int J=0;J<N;++J) {

(28)

Mở rộng: vấn đề với cấp phát nhớ động

• Memory Leaks: Rị rỉ nhớ xảy nhớ phân bổ không sử dụng lại không giải

(29)

Mở rộng: vấn đề với cấp phát nhớ động

• Double Free: giải phóng khối nhớ hai lần

(30)

Mở rộng: Con trỏ đến (Pointers to a constant)

• Một trỏ xác định để trỏ đến số

Điều có nghĩa trỏ khơng thể sử dụng để sửa đổi giá trị mà tham chiếu.

• int num = 5;

• const int limit = 500;

• int *pi; // Pointer to an integer

• const int *pci; // Pointer to a constant integer • pi = &num;

(31)

Mở rộng: Con trỏ (Constant pointers)

• Con trỏ khơng thể thay đổi, giá trị mà trỏ đến có thể thay đổi

• int num;

• int *const cpi = &num;

• Các lệnh sau hợp lệ

(32)

Truyền tham chiếu

• Hàm nhận tham số trỏ

void Swap(int *X, int *Y) { int Temp = *X;

*X = *Y; *Y = Temp; }

• Để hoán đổi giá trị hai biến A B

Swap(&A, &B);

(33)

Truyền tham chiếu

• Hàm nhận tham số tham chiếu

void Swap(int &X, int &Y){ int Temp = X;

X = Y;

Y = Temp; }

• Để hốn đổi giá trị hai biến A B

Swap(A, B);

(34)

Truyền tham chiếu

Khi hàm trả về tham

chiếu, có thể gọi hàm ở phía bên trái của phép gán.

#include <iostream.h> int X = 4;

int & MyFunc(){ return X;

}

int main(){

Cout << "X=“ << X << endl;

Cout << "X=“ << MyFunc() << endl;

MyFunc() = 20; // ~X=20

Cout << "X=“ << X << endl; return 0;

}

(35)

Đa hố tốn tử

• Định nghĩa lại chức tốn tử

có sẵn

 Thể phép toán cách tự nhiên hơn • Ví dụ: thực phép cộng, trừ số phức

 Trong C: Cần phải xây dựng hàm AddSP(),

TruSP()

 Không thể phép cộng trừ cho

biểu thức như: a=b+c-d+e+f-h-k

(36)

#include <stdio.h> struct SP {

double real; double img; };

SP SetSP(double real, double img); SP AddSP(SP C1,SP C2);

SP SubSP(SP C1,SP C2); void DisplaySP(SP C); int main(void) {

SP C1,C2,C3,C4;

C1 = SetSP(1.0,2.0); C2 = SetSP(-3.0,4.0);

cout << "\nSo phuc thu nhat:"; DisplaySP(C1); cout << "\nSo phuc thu hai:"; DisplaySP(C2); C3 = AddSP(C1,C2);

C4 = SubSP(C1,C2);

cout << "\nTong hai so phuc nay:"; DisplaySP(C3); cout << "\nHieu hai so phuc nay:"; DisplaySP(C4); return 0;

(37)

SP SetSP(double real,double img) { SP tmp;

tmp.real = real; tmp.img = img; return tmp;

}

SP AddSP(SP C1,SP C2) { SP tmp;

tmp.real = C1.real + C2.real; tmp.img = C1.img + C2.img; return tmp;

}

SP SubSP(SP C1,SP C2) { SP tmp;

tmp.real = C1.real - C2.real; tmp.img = C1.img - C2.img; return tmp;

}

void DisplaySP(SP C) {

(38)

C++

• C++ cho phép định nghĩa lại chức

tốn tử có sẵn cách tiện lợi tự nhiên Điều gọi đa hóa tốn tử.

• Một hàm định nghĩa tốn tử có cú pháp sau:

data_type operator operator_symbol ( parameters )

{ ……… }

Trong đó:

data_type: Kiểu trả về.

(39)

#include <iostream.h>

typedef struct SP { double real; double img;} SP;

SP SetSP(double real, double img); void DisplaySP(SP C);

SP operator + (SP C1, SP C2); SP operator - (SP C1, SP C2);

int main() {

SP C1,C2,C3,C4;

C1 = SetSP(1.1,2.0); C2 = SetSP(-3.0,4.0);

cout << "\nSo phuc thu nhat:"; DisplaySP(C1); cout << "\nSo phuc thu hai:"; DisplaySP(C2); C3 = C1 + C2;

C4 = C1 - C2;

cout << "\nTong hai so phuc nay:"; DisplaySP(C3); cout << "\nHieu hai so phuc nay:"; DisplaySP(C4); return 0;

(40)

SetSP(double real,double img) { SP tmp;

tmp.real = real; tmp.img = img; return tmp;

}

SP operator + (SP C1,SP C2) { SP tmp;

tmp.real = C1.real + C2.real; tmp.img = C1.img + C2.img;

return tmp; }

SP operator - (SP C1,SP C2) { SP tmp;

tmp.real = C1.real - C2.real; tmp.img = C1.img - C2.img;

return tmp; }

void DisplaySP(SP C) {

(41)

Ví dụ sử dụng trỏ hàm

void swapValue(int &value1, int &value2){ int temp = value1;

value1 = value2; value2 = temp; }

int main(){

void(*pSwap) (int &, int &) = swapValue; int a = 1, b = 5;

cout << "Before: " << a << " " << b << endl; (*pSwap)(a, b);

cout << "After: " << a << " " << b << endl; return 0;

}

(42)

Sắp xếp dãy số

bool ascending(int left, int right){ return left > right;

}

bool descending(int left, int right){ return left < right;

}

void selectionSort(int *arr, int length, bool (*comparisonFunc)(int, int)){

for (int i_start = 0; i_start < length; i_start++) { int minIndex = i_start;

for (int i_current = i_start + 1; i_current < length; i_current++){ if (comparisonFunc(arr[minIndex], arr[i_current])) {

minIndex = i_current; }

}

swap(arr[i_start], arr[minIndex]); // std::swap }

}

(43)

Sắp xếp dãy số int main() {

int arr[] = { 1, 4, 2, 3, 6, 5, 8, 9, }; int length = sizeof(arr) / sizeof(int);

cout << "Before sorted: "; printArray(arr, length);

selectionSort(arr, length, descending); cout << "After sorted: ";

printArray(arr, length); return 0;

}

(44)

Sắp xếp dãy số int main() {

int arr[] = { 1, 4, 2, 3, 6, 5, 8, 9, }; int length = sizeof(arr) / sizeof(int);

cout << "Before sorted: "; printArray(arr, length);

selectionSort(arr, length, ascending); cout << "After sorted: ";

printArray(arr, length); return 0;

}

(45)

Khái quát hóa hàm (Function templates)

#include <iostream> using namespace std; template <typename T> T maxval(T x, T y){

return (x > y) ? x : y; }

int main() {

int i = maxval(3, 7); // returns cout << i << endl;

double d = maxval(6.34, 18.523); // returns 18.523 cout << d << endl;

char ch = maxval('a', '6'); // returns 'a' cout << ch << endl;

return 0; }

(46)

Hàm nặc danh - cú pháp lambda

#include <iostream> using namespace std;

void stdio_doing(int n) { n = n + 10;

cout << n << " "; }

void for_each (int *arr, int n, void (*func)(int a)){ for (int i = 0; i < n; i++) {

func(*(arr + i)); }

}

int main(){

int arr[] ={1, 2, 3, 4, 5} , n = 5; for_each(arr, n, stdio_doing);

return 0;

(47)

Hàm nặc danh - cú pháp lambda #include <iostream>

using namespace std;

void for_each (int *arr, int n, void (*func)(int a)){ for (int i = 0; i < n; i++) {

func(*(arr + i)); }

}

int main(){

int arr[] ={1, 2, 3, 4, 5} , n = 5; for_each(arr, n, [] (int a){

a = a + 10;

cout << a << " "; });

return 0; }

47

Lợi ích lambda khơng thiết phải khai báo tên hàm nơi khác, mà tạo hàm sử dụng chỗ (thường tác vụ nhỏ - dùng lần hay có chỗ gọi hàm đó)

(48)

Hàm nặc danh - cú pháp lambda

(1) Mệnh đề bắt giữ (capture clause) (2) Danh sách tham số

(3) Tính bền vững lambda

(4) Ngoại lệ xảy lambda (5) Kiểu trả lambda

(6) Phần thân lambda

(49)

Hàm nặc danh - cú pháp lambda

Mệnh đề bắt giữ (capture clause)

49

[ ] Không s d ng b t kỳ bi n bên thân hàmử ụ ấ ế

e.g [ ]( int i){ return i+j; } //error j bi n bên ngồi khơng đế ược captured [& ] Đượ ục s d ng bi n bên qua tham chi u (ế ế by reference)

e.g [&]( int i){ j++; return i+j; } //changes made to j is reflected upon return

[=] Đượ ục s d ng bi n bên ngoài, nh ng d ng chép giá tr c a bi n (ế ị ủ ế by value)

e.g [=]( int i){ return i+j; } //j không thay đ i thân hàmổ

[&,j] B t kỳ bi n bên đấ ế ược captured qua tham chi u, ngo i tr bi n j đế ế ược captured qua giá tr ị

e.g [&,j]( int i){ j++; k++; return i+j+k; } //j tăng c c b k tăng giá tr cho c bên ụ

ngoài hàm

[=,j] B t kỳ bi n bên đấ ế ược captured qua giá tr , ngo i tr bi n j đị ế ược captured qua tham chi uế

e.g [ ]( int i){ j++; k++; return i+j+k; }

[this] Cho phép s d ng this (OOP) nh b n saoử ụ ả

[&,&j] Error j ghi l i theo tham chi u theo m c đ nhạ ế ặ ị

[=,this] Error s d ng ụ =, this captured theo m c đặ ược

[i,i] Error i b l p l iị ặ

[&this] Error không th l y đ a ch c a ể ấ ị ỉ ủ this

(50)

Ví dụ

#include <iostream> using namespace std; int main(){

int m = 0; int n = 0;

auto func = [&, n] (int a) mutable { m = ++n + a;

};

func(4);

cout << m << endl << n << endl; }

Kết quả:

5

(51)

Bài tập

• Xây dựng cấu trúc thời gian Time chứa thông

tin giờ, phút đa hóa tốn tử +, - cho cấu trúc thời gian này.

(52)

Bài tập

• Xây dựng hàm cấp phát động ma trận có kích

thước n x m.

(53)

Bài tập

• Xây dựng hàm cấp phát động ma trận có kích

thước n x m.

53

(54)

Bài tập

• Xây dựng hàm cấp phát động ma trận có kích

thước n x m.

54

(55)

Bài tập

• Xây dựng hàm cấp phát động ma trận có kích

thước n x m.

55

(56)

Một vài ví dụ tối ưu mã C, C++

switch ( queue ) {

case : letter = 'W'; break; case : letter = 'S'; break; case : letter = 'U'; break; }

Hoặc :

if ( queue == ) letter = 'W';

else if ( queue == ) letter = 'S';

else letter = 'U';

static char *classes="WSU"; letter = classes[queue];

(57)

Một vài ví dụ tối ưu mã C, C++

(x >= && x < max) có thể chuyển thành (unsigned)(x - min) < (max - min)

Giải thích:

int: -231 … 231 - 1

unsigned: … 232 - 1

Nếu x - >= 0: Hai biểu thức tương đương Nếu x - <= 0:

(unsigned) (x - min) = 232 + x – min

>= 231 > max - min

(58)

Một vài ví dụ tối ưu mã C, C++

int fact1_func (int n) { int i, fact = 1;

for (i = 1; i <= n; i++) fact *= i; return (fact);

}

int fact2_func(int n) { int i, fact = 1;

for (i = n; i != 0; i ) fact *= i; return (fact);

}

fact2_func nhanh hơn, phép thử != đơn giản <=

(59)

Số thực dấu phẩy động

• So sánh:

x = x / 3.0;

x = x * (1.0/3.0) ;

(biểu thức thực dịch)

• Hãy dùng float thay double

• Tránh dùng sin, exp và log (chậm gấp 10 lần * )

• Dùng x * 0.5 thay x / 2.0 • x+x+x thay x*3

• Mảng chiều nhanh mảng nhiều chiều • Tránh dùng đệ quy

(60)

Ví dụ Tính giai th a c a n

 Đ nh nghĩa không ị đ quyệ n!

n! = n * (n-1) * … * 1

 Đ nh nghĩa ị đ quyệ :

n! = 1 n u n=0ế

n * (n-1)! n u n>0ế Mã C++

int factorial(int n) { if (n==0) return 1; else

return (n * factorial(n -

(61)

Ví dụ Tính

S(n) = 1/(1*2) + 1/(2*3) + + 1/( n*(n+1) ) S(n) = 1/2 n==1

= S(n-1)+1/(n*(n+1))

float S(int n) {

if ( n==1) return 0.5;

(62)

Ví dụ Tính t ng giá tr c a dãy s H(n), bi t ị ủ ế H(n) = n n<3

= 2*H(n-1)*H(n-2) n>2

long H(int n) {

if (n<3) return n;

else return 2*H(n-1)*H(n-2); }

long Tong(int n) { long tg=0;

for( int i=1; i<=n;i++) tg+=H(i);

(63)

Bài tập

Tính X(n) v i ớ

Xo = 1

(64)

Ví dụ X(n) = 1,2,3,5,11,41……Y(n) = 1,1,2,6,30,330 …

void main() {    int n;

   printf("\n Nhap n = ");    scanf("%d",&n);

   printf( "\n X = %d " ,X(n));    printf( "\n Y = %d " , Y(n));    getch();

}

long Y(int n); //prototype cua ham y long X(int n) {

   if(n==0)       return 1;    else

      return X(n-1) + Y(n-1);       }

long Y(int n) {    if(n==0)

      return 1;    else

(65)

Bài tập 1

(66)

Bài tập 2

•Xây d ng hàm đ ự ệ ki m tra xem ể m t m ng s nguyên có đ i ộ ả ố ố

(67)

Bài tập 2 •Phân tích

u c u : ki m tra tính đ i x ng c a m t m ng ể ố ứ ủ ộ ả

t ph n t t hai đ u c a m ngừ ầ ừ ầ ủ ả

Kích thước đ quy : s ph n t c a m ngố ầ ủ ả

Đi m d ng đ quy : phát hi n hai ph n t n m ệ ầ ằ

t i v trí đ i x ng khơng giá tr ho c ạ ị ố ứ ị ặ

ki m tra h t ph n t đ u đ i x ngể ế ầ ề ố ứ

Trường h p t ng quát : ph n t n m t i ầ ằ ạ

các v trí i j đ i x ng có giá tr ki m tra ị ố ứ ị ể

(68)

Bài tập 3

•Xây d ng hàm đ ự ệ quy ki m tra ể m t m ng có giá tr ph n t ộ ả ị ầ ử

theo th t tăng d n (ho c gi m ứ ự ầ ặ ả

(69)

Bài tập 4

•M t palindrome m t t hay m t ộ ộ ừ ộ câu, đ c xuôi ngọ ược đ u gi ng nh ề ố ư

nhau Vi t chế ương trình, v i gi i ớ ả

thu t đ quy, đ c m t dòng t bàn ậ ệ ọ ộ ừ

phím vào báo cho bi t có ph i ế ả

(70)

Bài tập 5

•Xây d ng hàm đ quy đ o ngự ệ ả ược m t m ng s nguyên?ộ ả ố

•Xây d ng hàm đ o ngự ả ược m t ộ

m ng s nguyên không dùng đ ả ố ệ

(71)

Bài tập

•Vi t hàm đ quy tính giá tr ph n t r i tính t ng c a ế ệ ị ầ ồ ổ ủ

dãy s sau ố

1,2,3,6,11,20,37,68,125

•Vi t hàm đ quy tính giá tr ph n t r i tính t ng c a ế ệ ị ầ ồ ổ ủ

dãy s sau : ố

(72)

Bài tập

•Vi t hàm đ quy tính ph n t c a dãy s sau v i n ế ệ ầ ủ ố ớ

ph n t (n>4), r i tính t ng ph n t c a dãy sầ ử ồ ổ ầ ủ ố

(73)

•Kh ử đ quyệ v i hàm tính giai th aớ ừ

int FAC ( int n ) { int k = 0;

int F = 1;

while ( k < n ) F = ++k * F; return (F);

}

•Kh đ quy v i hàm tính S(n)ử ệ ớ

int S ( int n ) {

int k = , tg = ; while ( k < n ) {

k ++ ;

if (k%2 == 1) tg + = * k -1; else tg -= * k + ;

}

(74)

Ví dụ

Tìm ước chung lớn nhất

Gi i thu t đ quy

int USCLN(int m, int n) {

if (n == 0) return m;

else USCLN(n, m % n);

}

• X là( m , n )

• P(X) USCLN(m ,n)

• B(X) n ==

• D(X) l nh return mệ

• A(X) l nh r ngệ ỗ

• f(X ) f(m,n) = ( n , m mod n )

Kh đ quyử ệ

int USCLN(int m , int n ) {

while(n != ) { int sd = m % n ; m = n ;

n = sd ; }

(75)

Ví dụ

Bài tốn Tháp Hà Nội

Đ quy

THN(n,X,Y,Z) ≡ if(n > 0) {

THN (n - 1, X, Z, Y); Move (X, Z );

THN (n - 1, Y, X, Z); }

Trong đó

• Bi n X b (n,X,Y,Z)ế ộ

• C(X) n<=0

• D(X), A(X) r ngỗ

• B(X) = B(n,X,Y,Z) move(X, Z)

• f(X) = f(n,X,Y,Z) = (n-1,X,Z,Y)

• g(X) = g(n,X,Y,Z) = (n-1,Y,X,Z)

Kh đ quyử ệ

THN {

Create_Stack (S) ;

Push (S ,(n,X,Y,Z,1)) ; Repeat

While (n > 0) begin

Push (S ,(n,X,Y,Z,2)) ; n = n - 1;

Swap (Y,Z) ; end ;

Pop (S,(n,X,Y,Z,k)) ;

if ( k <> ) then begin Move (X ,Z ) ;

n = n - ; Swap (X,Y) ; end ;

(76)

Ví dụ Cho dãy s 1,2,3,7,14,27,55,110,219 ố Vi t hàm đ quy tính s h ng th n c a dãy ế ệ ố ạ ứ ủ

s (n > nh p t bàn phím), r i tính t ng ố ậ ừ ồ ổ

s h ng c a dãyố ạ ủ

Sau đó, kh đ quy chử ệ ương trình trên Cơng th c t ng quátứ ổ

S(n) = n, n <4

(77)

Ví dụ Chương trình đ quyệ

int S(int n) { if (n<4)

return n; else

return S(n-1)+S(n-2)+S(n-3)*2; }

int main() {

int n,i,Tong=0;

printf("\n Vao n :"); scanf("%d",&n);

for(i=1;i<=n;i++) Tong+=S(i);

(78)

Ví dụ Kh đ quyử ệ

int main() {

int i,n,T=6; F1,F2,F3,F; printf("\n Vao n: "); scanf("%d",&n);

if (n==1) T=1;

else if (n==2) T=3; else if (n==3) T=6; else {

F1=1; F2=2; F3=3; for(i=4;i<=n;i++) {

F=2*F1+F2+F3; T+=F;

F1=F2; F2=F3; F3=F; }

(79)

Ví dụ Kh đ quy (dùng m ng)ử ệ ả

int main() {

int i,n,T=6, F[4]={1,2,3,7}; printf("\n Vao n : ");

scanf("%d",&n); if (n==0) T=1;

else if (n==1) T=3;

else if (n==2) T=6; else {

for(i=3;i<=n;i++) {

F[i%4] =

F[(i-1)%4]+F[(i-2)%4]

+2 * F[(i-3)%4]; T+=F[i%4];

} }

printf("\n Tong = %d ",T); getch();

(80)

Bài tập

•Vi t hàm đ quy tính giá tr ph n t r i tính t ng c a ế ệ ị ầ ồ ổ ủ

dãy s sau, sau vi t chố ế ương trình dướ ại d ng không đ ệ

quy:

T=1+2+3+6+11+20+37+68+125+

•Vi t hàm đ quy tính giá tr ph n t r i tính t ng c a ế ệ ị ầ ồ ổ ủ

dãy s sau, sau vi t chố ế ương trình dướ ại d ng khơng đ ệ

quy:

(81)

Bài tập

•Vi t hàm đ quy tính ph n t c a dãy s sau v i n ế ệ ầ ủ ố ớ

ph n t (n>4), r i tính t ng ph n t c a dãy sầ ử ồ ổ ầ ủ ố

1,2,3,4,4,5,8,11,12,14,21,30,35,40,56,… 1,2,3,4,6,9,14,21,32,48,73,110,167,252,

•Sau vi t l i tồn b chế ạ ộ ương trình tính t ng dãy s ổ ố

(82)

Bài tập

•Xây d ng hàm đ quy đ o ngự ệ ả ược các ph n t m t danh sách ầ ử ộ

liên k t đ n?ế ơ

•Xây d ng hàm đ o ngự ả ược ph n ầ t m t danh sách liên k t đ n ử ộ ế ơ

(83)

Hướng dẫn

•Đ quy?ệ

•Đi m neo / d ng đ quy: NULL / ch có nútể ừ ệ ỉ

•Thao tác đ quy:ệ

•1 Chia danh sách thành hai ph n – node đ u tiên ầ ầ

ph n l i c a ầ ạ ủ danh sách

•2 Th c hi n đ o ngự ệ ả ược đ quy ệ cho ph n l i c a ầ ạ ủ

danh sách

•3 K t n i ph n l i c a ế ố ầ ạ ủ danh sách v i node đ u tiênớ ầ

(84)

Hướng dẫn

Gi i pháp sau có khơng?ả Node* reverse(Node* head) {

if (head == NULL || head->next == NULL) return head;

Node* rest = reverse(head->next); head->next->next = head;

head->next = NULL; return rest;

(85)

Hướng dẫn •Kh đ quy? ử ệ

 dùng vòng

(86)

Hướng dẫn

Gi i pháp sau có khơng?ả

void reverse() {

Node* current = head;

Node *prev = NULL, *next = NULL;

while (current != NULL) { next = current->next; current->next = prev;

prev = current; current = next; }

(87)

8

Bài tập: Kiểm tra chu trình danh sách nối đơn

▪ Định nghĩa danh sách liên kết đơn gồm giá trị nguyên, viết chương trình xác định danh sách liên kết có chứa chu trình hay khơng.

▪ Phân tích

▫ Trong ví dụ có tồn chu trình:

825371645371645 …

(88)

8

Bài tập: Kiểm tra chu trình danh sách nối đơn

▪ Thuật toán: Floyd's Cycle-Finding Algorithm

▫ Đặt hai trỏ: trỏ di chuyển chậm một trỏ di chuyển nhanh

▹ Con trỏ chậm: khởi tạo trỏ vào phần tử đầu danh sách (Head), lần lặp di chuyển sang phần tử (1 bước)

▹ Con trỏ nhanh: khởi tạo trỏ vào phần tử đầu danh sách (Head), lần lặp di chuyển sang phần tử phần tử (2 bước)

▫ Nếu sau số lần lặp hữu hạn mà hai trỏ cùng trỏ vào nút  danh sách tồn chu

trình

(89)

8

Bài tập: Kiểm tra chu trình danh sách nối đơn

int kiemtrachutrinh(Node *head){

Node* slow = head, *fast = head; //khởi tạo trỏ

while(slow && fast && fast->next){

slow = slow->next; //di chuyển trỏ chậm

fast = fast->next->next;//di chuyển trỏ nhanh

if(fast==slow){ //nếu có chu trình

return 1; }

}

return 0; //nếu khơng có chu trình

(90)

9

Bài tập 2

▪ Xây dựng chương trình khai báo danh

sách liên kết đơn chứa trị nguyên

▪ Thực hiện: tách danh sách thành

danh sách liên kết đơn con, danh sách liên kết đơn chứa phần tử giá trị nguyên tăng dần

(91)

Bài tập

S d ng ử ụ danh sách móc n i kép v i nút đ u gi , xây d ng ự toán qu n lý m SV đ n gi n, v i ch c sau ả ể ơ ả ớ ứ

1. Nh p d li u vào danh sáchậ ữ ệ

2. Hi n th d li u l p theo th t tênể ị ữ ệ ớ ứ ự

3. Tìm ki m k t qu theo tênế ế ả

4. S p x p theo m trung bìnhắ ế ể

V i thông tin v m i sinh viên đớ ề ỗ ược đ nh nghĩa c u trúc sauị ấ

typedef struct {

int masv; // mã hiệu sv char malop[12];

(92)

9

Bài tập 3

▪ Viết chương trình nhập vào mảng các số nguyên, xác định xem liệu có thể chia mảng thành hai mảng con có tổng phần tử mảng là nhau.

▫ Ví dụ: mảng {1, 5, 11, 5} chia được (hai mảng {1, 5, 5}

{11})

(93)

Bài tập

▪S a chử ương trình đ tính tốn k t qu c a bi u ể ế ả ủ ể

th c h u t v i toán h ng t ng quát (có th s th c, ứ ậ ố ớ ạ ổ ể ố ự

có th âm…)ể

▪Xây d ng chự ương trình chuy n đ i bi u th c t trung ể ổ ể ứ ừ

t sang h u t , bi u th c trung t xâu ký t v i toán ố ậ ố ể ứ ố ự ớ

(94)

Bài tập 4

▪Vi t m t chế ộ ương trình:

Nh p vào t bàn phím m t s nguyên d ộ ố ương có N ch s ữ ố

Nh p vào m t giá tr nguyên d ương M

Hãy th c hi n xoá M ch s s N đ thu đ ữ ố ược s l i sau xố l n nh t có th , xây d ng thu t

toán s d ng Stackử ụ .

Ví d : s 2019ụ ố ▸Xố ch s : 219ữ ố

▸Xoá ch s : 29ữ ố

(95)

9

Xoá để số lớn nhất ▪ Input:

▫ Số nguyên dương có N chữ số

▫ M: số chữ số cần xoá (0<= M < N)

▪ Output:

▫ Số lớn sau xoá M chữ số

▪ Phân tích

▫ Chuyển đổi số thành xâu ký tự để thuận tiện xử lý

▫ Nhận thấy xóa mà số lớn

lần xóa chữ phải tạo số lớn nhất

(96)

9

Xoá để số lớn nhất ▪ Phân tích: sử dụng ngăn xếp

▸ Dãy ln dãy lớn tạo xóa

▸ Stack chứa chữ số chọn

▫ Ví dụ: số 3973811 gồm N=7 chữ số, cần xoá M=3 chữ số

▸ Duyệt chữ số từ trái sang phải, stack ban đầu rỗng

▸ Đọc chữ số đầu tiên: M=3  push vào stack ▹ Stack: (cần xoá M=3)

▸ Đọc chữ số tiếp theo: M=3  so sánh với chữ số

trong đỉnh stack: >  pop khỏi stack push

vào thay thế, chữ số bị xoá

▹ Stack: (cần xoá M=2)

▸ Đọc chữ số tiếp theo: M=2  so sánh với chữ số

(97)

9

Xoá để số lớn nhất ▪ Phân tích: sử dụng ngăn xếp

▫ Ví dụ: số 3973811 gồm N=7 chữ số, cần xoá M=3 chữ số

▸ Đọc chữ số tiếp theo: M=2  so sánh với chữ số

trong đỉnh stack: <  push vào stack ▹ Stack: (cần xoá M=2)

▸ Đọc chữ số tiếp theo: M=2  so sánh với chữ số

trong đỉnh stack: >  pop khỏi stack (M=1),

>  pop khỏi stack (M=0) push vào thay

thế, chữ số bị xoá

▹ Stack: (cần xoá M=0)

▸ Đọc chữ số tiếp theo: M=0  push vào stack ▹ Stack: (cần xoá M=0)

▸ Đọc chữ số tiếp theo: M=0  push vào stack ▹ Stack: 1 (cần xoá M=0)

(98)

▪ Thứ tự trước: 15, 6, 3, 2, 4, 7, 13, 9, 18, 17, 20

▪ Thứ tự giữa: 2, 3, 4, 6, 7, 9, 13, 15, 17, 18, 20

▪ Thứ tự sau: 2, 4, 3, 9, 13, 7, 6, 17, 20, 18, 15

Ngày đăng: 06/04/2021, 14:14

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w