Tuesday, January 20, 2015

hàm xem danh sách liên kết đơn.

Xem danh sách liên kết đơn.
Danhsách liên kết đơn được tạo bởi các ô nhớ chứa dữ liệu cần lưu trữ và được liên kết với nhau thành một danh sách. Mỗi phần tử của danh sách liên kết được chia làm 2 phần. Là phần dữ liệu lưu trữ (data) và phần liên kết(link).
 Ø phần dữ liệu lưu trữ (data).
Phần này có thể chứa các số nguyên, số thực, hoặc tập hợp các số nguyên số thực và các xâu. Tùy thuộc vào mục đích sử dụng.
 Ø phần liên kết(link).
Phần này chứa biến con trỏ. Để lưu trữ vị trí ô nhớ của phần tử tiếp theo cần tham chiếu.

Nhìn sơ qua hình trên ta thấy. Muốn xem danh sách liên kết đơn thì ta phải biết được địa chỉ của phần tử đầu tiên(ta thường hay dùng con trỏ f để lưu) . Sau đó lần theo phần link để đọc các phần tử tiếp theo cho đến khi gặp NULL (dấu hiệu kết thúc danh sách liên kết) thì kết thúc việc xem dslk đơn.
Vậy hàm xem chỉ thực hiện công việc xem đơn thuần nên ta sử dụng hàm kiểu void. Truyền vào hàm con trỏ fchứa địa chỉ ô nhớ phần tử  đầu tiên của danh sách liên kết.
·        void xem(node *f)
và việc xem danh sách liên kết đơn ta phải sử dụng một biến con trỏ trung gian để duyệt từ đầu đến cuối danh sách. ở đây chúng ta sử dụng con trỏ p. Sở dĩ phải dùng biến trung gian bở vì nếu sử dụng con trỏ f thì sẽ làm mất địa chỉ ô nhớ đầu tiên. Dẫn đến không thể dựa vào điểm nào để lần ra danh sách đồng nghĩa với việc mất danh sach liên kết.
·        node *p=f;
Để duyệt từ vị trí đầu tiên đến (vị trí con trỏ f) vị trí cuối cùng ( phần tử có phần link bằng  NULL)của danh sách liên kết ta sử dụng vòng lặp whilevới điều kiện dừng là (p!=NULL) và mỗi lần lặp thì con trỏ p trỏ lên 1 vùng nhớ của phần tử tiếp theo. (p=p->link;)
Sơ qua thì hàm xem chúng ta xây dựng như sau,
void xem(node *f)
{
     node *p=f;
     while(p!=NULL)
     {
          /*
          phần đọc dữ liệu phần data.
          */
          p=p->link;
     }
}
Từ yêu cầu bài toán mà ta thay đổi phần đọc dữ liệu data sao cho phù hợp.

Ví dụ như phần data chưa mỗi biến info kiểu int.
typedef structnode
{
     int info;
     node *link;
};
// ham xem danh sach lien ket
void xem(node *f)
{
     node *p=f;
     while(p!=NULL)
     {
          printf("%5d",p->info);
          p=p->link;
     }
}

Ví dụ như phần data chưa mỗi biến info kiểu float.
typedef structnode
{
     float info;
     node *link;
};
// ham xem danh sach lien ket
void xem(node *f)
{
     node *p=f;
     while(p!=NULL)
     {
          printf("%5.2f",p->info);
          p=p->link;
     }
}

Các cách đọc dữ liệu cần linh hoạt. phù hợp với yêu cầu bài toán.
Gọi hàm chỉ làm thủ tục đơn giản là xem(f);
Code test thử hàm. c/c++
#include <stdio.h>
#include <conio.h>
typedef struct node
{
     intinfo;
     node *link;
};
// ham xem danh sach lien ket.
void xem(node *f)
{
     node *p=f;
     while(p!=NULL)
     {
           printf("%5d",p->info);
           p=p->link;
     }
}
//Nhap danh sach lien ket don LIFO.
node *nhaplifo(node *f,int n)
{
     node *p;
     for(int i=0;i<n;i++)
     {
           p=new(node);
           printf("\nNhap phan tu:  ");
           scanf("%d",&p->info);
           p->link=f;
           f=p;
     }
     returnf;
}
int main()
{
     node *f=NULL;
     intn;
     printf("\nNhap so phan tu cua dslk : ");
     scanf("%d",&n);
     f=nhaplifo(f,n);
     printf("\nDanh sach vua nhap :  ");
     xem(f);
     getch();
}

Danh sách liên kết, dslk, xem danh sách liên kết, lifo, fifo, cu trúc d liu gii thut. ctdlgt.

Friday, December 26, 2014

Bài toán phân tích số (đệ quy quay lui)

Bài toán phân tích số.
Cho một số nguyên dương n<=30, hãy liệt kê tất cả các cách phân tích số n thành tổng của các số nguyên dương, các cách phân tích số là hoán vị của nhau chỉ tính là 1 cách.
Hướng làm bài toán phân tích số theo đệ quy quay lui:
     1.     Ta sẽ lưu nghiệm trong mảng x, ngoài ra có một mảng t. Mảng t xây dựng như sau: t[i] sẽ là tổng các phần tử trong mảng x từ x[1] đến x[i]: 
      t[i]=x[1]+x[2]+ ……+ xi.
     2.     Khi liệt kê các dãy x có tổng các phần tử đúng bằng n, để tránh sự trùng lặp ta đưa thêm ràng buộc x[i-1]<=x[i].
    3.     Vì số phần tử thực sự của mảng x là không cố định nên thủ tục in ra dùng để in ra một cách phân tích phải có thêm tham số để cho biết sẽ in ra bao nhiêu phần tử.
     4.     Thủ tục đệ quy sẽ thử các giá trị có thể nhận x[i] ( x[i]>=x[i-1]).
     5.     Khi nào thì in kết quả, khi nào thì gọi đệ quy tiếp.
Lựu ý : t[i-1] là tổng của tất cả các phần tử từ x[i] đến x[i-1] do đó
·        Khi t[i] = n tứ là ( x[i]=n-t[i-1] ) thì in kết quả.
·        Khi tìm tiếp, x[i+1] sẽ phải lớn hơn hoặc bằng x[i].
Mặt khác t[i+1] là tổng của các số từ x[1] tới x[i+1] không được vượt quá n.
Vậy ta có t[i+1] <= n
 ót[i-1] + x[i] +x[i-1]<=n
 óx[i] + x[i+1] <=n-t[i-1]
 tức là x[i] <= ( n-t[i-1])/2.
Một cách dễ hiểu ta gọi đệ quy tìm tiếp khi giá trị x[i] được chọn còn cho phép chọn thêm một phần tử khác lớn hơn hoặc bằng nó mà khong làm tổng vượt quá n. còn ta in kết quả khi x[i] mang giá trị đúng bằng số thiếu hụt của tổng [i-1] phần tử đầu so với n.
     6.     Vậy thủ tục đệ quy thử các giá trị cho x[i] có thể mô tả như sau: (để tổng quát cho i = 1, ta đặt x[0] = 1 tà t[0] = 0).
·        Xét các giá trị của xi từ x[i-1] đến (n-t[i-1])/2, cập nhật t[i]=t[i+1] + x[i] và gọi đệ quy tiếp.
·        Cuối cùng xét giá trị x[i] = n – t[i-1] và in ra kết quả từ x[1] đến x[i].
Input: nhập số nguyên dương n từ bàn phím  n<=30.
Outout: in ra màn hình các cách phân tích các số nguyên tương ứng.





Code đệ quy C/C++.

#include <stdio.h>
#include <conio.h>
intx[31],t[31],n;
voidkhoitao()
{
      printf("\nNhap n = ");
      scanf("%d",&n);
      x[0]=1;
      t[0]=0;
}
void xuat(int k)
{
      printf("\n%d = ",n);
      for (inti=1;i<k;i++) printf(" %d + ",x[i]);
      printf(" %d",x[k]);
}
voidphantich(int i)
{
      for(intj=x[i-1];j<=((n-t[i-1])/2);j++)
      {
            x[i]=j;
            t[i]=t[i-1]+j;
            phantich(i+1);
      }
      x[i]=n-t[i-1];
      xuat(i);
}
intmain()
{
      khoitao();
      phantich(1);
      getch();
}




Code theo tệp.     
                                                                     
Input: file văn bản PTSINP.TXT chứa các số nguyên dương cách nhau ít nhất 1 kí tự trống hoặc dấu xuống dòng  n<=30.

Outout: file PTSOUT.TXT ghi các cách phân tích các số nguyên tương ứng.

Để đơn giản hóa việc nhập và xem dữ liệu mình thực hiện thao tác 2 file input và output trên nền ổ C:
      C:\\PTSINP.txt
      C:\\PTSOUT.txt

PTSEINP.TXT
PTSOUT.TXT
3
6
7
11
3 =  1 +  1 +  1
3 =  1 +  2
3 =  3
6 =  1 +  1 +  1 +  1 +  1 +  1
6 =  1 +  1 +  1 +  1 +  2
6 =  1 +  1 +  1 +  3
6 =  1 +  1 +  2 +  2
6 =  1 +  1 +  4
6 =  1 +  2 +  3
6 =  1 +  5
6 =  2 +  2 +  2
6 =  2 +  4
6 =  3 +  3
6 =  6
7 =  1 +  1 +  1 +  1 +  1 +  1 +  1
7 =  1 +  1 +  1 +  1 +  1 +  2
7 =  1 +  1 +  1 +  1 +  3
7 =  1 +  1 +  1 +  2 +  2
7 =  1 +  1 +  1 +  4
7 =  1 +  1 +  2 +  3
7 =  1 +  1 +  5
7 =  1 +  2 +  2 +  2
7 =  1 +  2 +  4
7 =  1 +  3 +  3
7 =  1 +  6
7 =  2 +  2 +  3
7 =  2 +  5
7 =  3 +  4
7 =  7
11 =  1 +  1 +  1 +  1 +  1 +  1 +  1 +  1 +  1 +  1 +  1
11 =  1 +  1 +  1 +  1 +  1 +  1 +  1 +  1 +  1 +  2
11 =  1 +  1 +  1 +  1 +  1 +  1 +  1 +  1 +  3
11 =  1 +  1 +  1 +  1 +  1 +  1 +  1 +  2 +  2
11 =  1 +  1 +  1 +  1 +  1 +  1 +  1 +  4
11 =  1 +  1 +  1 +  1 +  1 +  1 +  2 +  3
11 =  1 +  1 +  1 +  1 +  1 +  1 +  5
11 =  1 +  1 +  1 +  1 +  1 +  2 +  2 +  2
11 =  1 +  1 +  1 +  1 +  1 +  2 +  4
11 =  1 +  1 +  1 +  1 +  1 +  3 +  3
11 =  1 +  1 +  1 +  1 +  1 +  6
11 =  1 +  1 +  1 +  1 +  2 +  2 +  3
11 =  1 +  1 +  1 +  1 +  2 +  5
11 =  1 +  1 +  1 +  1 +  3 +  4
11 =  1 +  1 +  1 +  1 +  7
11 =  1 +  1 +  1 +  2 +  2 +  2 +  2
11 =  1 +  1 +  1 +  2 +  2 +  4
11 =  1 +  1 +  1 +  2 +  3 +  3
11 =  1 +  1 +  1 +  2 +  6
11 =  1 +  1 +  1 +  3 +  5
11 =  1 +  1 +  1 +  4 +  4
11 =  1 +  1 +  1 +  8
11 =  1 +  1 +  2 +  2 +  2 +  3
11 =  1 +  1 +  2 +  2 +  5
11 =  1 +  1 +  2 +  3 +  4
11 =  1 +  1 +  2 +  7
11 =  1 +  1 +  3 +  3 +  3
11 =  1 +  1 +  3 +  6
11 =  1 +  1 +  4 +  5
11 =  1 +  1 +  9
11 =  1 +  2 +  2 +  2 +  2 +  2
11 =  1 +  2 +  2 +  2 +  4
11 =  1 +  2 +  2 +  3 +  3
11 =  1 +  2 +  2 +  6
11 =  1 +  2 +  3 +  5
11 =  1 +  2 +  4 +  4
11 =  1 +  2 +  8
11 =  1 +  3 +  3 +  4
11 =  1 +  3 +  7
11 =  1 +  4 +  6
11 =  1 +  5 +  5
11 =  1 +  10
11 =  2 +  2 +  2 +  2 +  3
11 =  2 +  2 +  2 +  5
11 =  2 +  2 +  3 +  4
11 =  2 +  2 +  7
11 =  2 +  3 +  3 +  3
11 =  2 +  3 +  6
11 =  2 +  4 +  5
11 =  2 +  9
11 =  3 +  3 +  5
11 =  3 +  4 +  4
11 =  3 +  8
11 =  4 +  7
11 =  5 +  6
11 =  11

Code đệ quy bài phân tích số C/C++

#include <stdio.h>
#include <conio.h>
intx[31],t[31],n;
voidkhoitao(FILE *u)
{
      fscanf(u,"%d",&n);
      x[0]=1;
      t[0]=0;
}
void xuat(int k,FILE *v)
{
      fprintf(v,"\n%d = ",n);
      for (inti=1;i<k;i++) fprintf(v," %d + ",x[i]);
      fprintf(v," %d",x[k]);
}
voidphantich(int i,FILE *v)
{
      for(intj=x[i-1];j<=((n-t[i-1])/2);j++)
      {
            x[i]=j;
            t[i]=t[i-1]+j;
            phantich(i+1,v);
      }
      x[i]=n-t[i-1];
      xuat(i,v);
}
intmain()
{
      FILE *u,*v;
      u=fopen("C:\\PTSINP.txt","rt");
      v=fopen("C:\\PTSOUT.txt","wt");
      while (!feof(u))
      {
            khoitao(u);
            phantich(1,v);
      }
      fclose(u);
      fclose(v);
      printf("\nHoan Tat. Moi xem ket qua tai C:\\PTSOUT.txt ");
      getch();
}



Thẻ : đệ quy , đệ quy cấu trúc dữ liệu giải thuật .dequy dequyctdlgt

Mong các bạn góp ý và  nhấn G+ ủng hộ blog.