1. Trang chủ
  2. » Trung học cơ sở - phổ thông

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

98 18 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

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ả h[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 vng 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 cu

ủa phầầ

n tửủ

ma

ủng

-

Sắắ

p xếắ

p phầầ

n tửủ

ma

ủng theo

(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ầắp phát vùng nhớ cho ma trận A if(!AllocMatrix(&A,M,N))

{

cout << "Khong du bo nho! " << endl;

return 1; }

//Cầắp phát vùng nhớ cho ma trận B if(!AllocMatrix(&B,M,N))

{

cout << "Khong du bo nho! " << endl;

FreeMatrix(A); return 1; }

(25)

//Cầắp 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);

(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ầắp 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;

}

• Để hố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;

}

• Để hoá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 hoá toá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ề.

operator_symbol

: Ký hiệu toán tử.

(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: -2

31

… 2

31

- 1

unsigned: … 2

32

- 1

Nếu

x - >= 0

: Hai biểu thức tương đương

Nếu

x - <= 0

:

(unsigned) (x - min) = 2

32

+ x – min

>= 2

31

> 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

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 -

1));

(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

X

o

= 1

X

n

= canba(n)*X

o

+ canba(n-1)*X

1

+ + canba(1)*X

n-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

Xây d ng hàm đ quy in đ o

(66)

Bài tập 2

Xây d ng hàm đ ki m tra xem

ệ ể

(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

(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

(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

(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 :

1,2,3,7,13,23,43,79,145

(72)

Bài tập

Vi t hàm đ quy tính ph n t c a dãy s sau v i n

ế

ầ ủ

(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:

T=1+2+3+7+13+23+43+79+145+

(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

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

ầ ử

trong m t danh sách liên k t đ n không

ế ơ

(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?

ử ệ

(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; }

}

(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})

Ví dụ: mảng {1, 5, 3} không chia

(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

ậ ố

ự ớ

h ng t ng quát phép toán đ u tiên nh sau :

ộ ư

ư

(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 cịn l i sau xố l n nh t có th , xây d ng thu t

tốn s d ng Stack.

ử ụ

Ví d : s 2019

ụ ố

▸Xoá 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ử

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ố đỉ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ố đỉnh stack: <  push vào stack

(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ố đỉ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:20

TỪ KHÓA LIÊN QUAN

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

TÀI LIỆU LIÊN QUAN

w