SLIDE1

Showing posts with label giai thuat. Show all posts
Showing posts with label giai thuat. Show all posts

Thursday, June 11, 2015

hàm xóa node trong cây nhị phân tìm kiếm

hàm xóa node trong cây nhị phân tìm kiếm
void thaythe(tree &t,node *p)
{
    if(t->left) thaythe(t->left,p);
    //nếu nhánh bên trái còn tức là khác NULL thì tiếp tực nhảy đến nhánh bến trái
    //cho đến khi nào nó là cực trái thì thôi
    else//nó đã là node cực trái
    {
        p->key=t->key;
        //p là con trỏ truyền vào, mọi thay đỏi về bộ nhớ, ô nhớ hay giá trị đều thay đỏi trên
        //hàm xoa(tree &t,int x) đã gọi nó.
        //lúc này p là node cần xóa ở hàm xóa, ta không xóa node mà thay thế giá trị cho nó
        //rồi chuyển nó đến 1 ô nhớ khác, 
        //ô nhớ mà t đang tìm để thay thế để hàm xoa() gọi delete nó.
        p=t;//node t là node ta đã tìm ra để thay thế 
        //nên p=t; tức là sẽ xóa T thay cho p ban đầu
        //nên p(node sẽ xóa ở hàm ngoài) nhảy đến ô nhớ của node thay thế là node T , p=t;
        t=t->right;
        //vì t sẽ bị xóa thông qua p nên t phải nhay đến nhánh bên phải 
        //để làm liến mạch liên kết với cha như đã lý giải ở hàm xóa
        //vì sao lại trỏ right là không phải trỏ left?
        //vì T là node thay thế, là node cực trái, 
        //tức nhánh trái = NULL còn nhánh phải có thể khác NULL
        //hoắc bằng NULL, t không cần xác định, chỉ cần 
        //trỏ t->right để làm liền mạch liên kết đến node cha đã gọi đến nó
        //là ok.
    }
}
void xoa(tree &t,int x)//hàm xóa node trong cây nhị phân tìm kiếm
{
    if(t)//nếu cây t!=NULL
    {
        if(x<t->key) xoa(t->left,x);//nếu x < key xóa bên trái
        else if(x>t->key) xoa(t->right,x);//xóa bên phải
        else//đã tìm thấy node cần xóa
        {
            node *p=t;//gán node cần xóa cho p
            if(t->left==NULL) t=t->right;
            //nếu node cần xóa có 1 cây con bên phải
            else if(t->right==NULL) t=t->left;
            //hoặc 1 cây con bên trái
            //thì T được truyền vào trong đối số hàm nhảy sang trái hoăc sang phải như trên
            //vì sao nó liên kết được với node cha??
            //vì node cha đang trỏ đến con trỏ t (tree &t) 
            //ở dạng tham chiếu luôn nên mọi thay đổi trên t
            //thì đều thay đổi trên cấu trúc của node cha, node gọi đến hàm này
            //vì thế node cha của node cần xóa hiện tại 
            //sẽ trỏ đến t, và khi t=t->right; thì
            //node cha của node cần t cần xóa vẫn đang trỏ 
            //đến t với giá trị là ô địa chỉ mới t->right;
            else thaythe(t->right,p);
            //nếu ndoe t cần xóa có 2 nhánh con thì tìm node cực trái của nhánh phải
            //hoặc ngược lại cũng có thể được
            delete p;
        }
    }
    //lưu ý cần nhớ.
    //khi đối số của hàm là còn trỏ hoặc tham chiếu 
    //thì mọi thay đổi trên nó đều thay đổi đến biến của hàm đã gọi nó, 
    //thay đổi đến cụ diện chung của biến, của hàm đã gọi nó.
}

Thursday, June 4, 2015

đề thi và đáp án môn cấu trúc dữ liệu và giải thuật

đề thi và đáp án môn CTDL & GT cấu trúc dữ liệu và giải thuật , lập trình c/c++
1. tạo 2 danh sách liên kết đơn l1,l2 với giá trị của các node trong danh sách là số nguyên.việc nhập mỗi danh sách kêt thúc khi nhập vào số 0. in các giá trị l1, l2 ra màn hình
2. viết hàm merge thực hiện việc trộn luân phiên danh sách l2 vào l1 sao cho sau khi trộn l2 rỗng
3. viết hàm sắp xếp danh sách l1 giảm dần theo trường dữ liệu.
4. chèn 1 số nguyên vào danh sách sao cho vẫn đảm bảo tính giảm dần của l1.

code bài làm:

#include<iostream>
using namespace std;
typedef struct tagnode
{
    int x;
    struct tagnode *next;
}node;
typedef struct taglist
{
    node *dau;
    node *cuoi;
}list;
void khoitao(list &l)
{
    l.dau=l.cuoi=NULL;
}
node *taonode(int x)
{
    node *p=new node;
    if(p==NULL) exit(1);
    p->x=x;
    p->next=NULL;
    return p;
}
void themcuoi(list &l,node *p)
{
    if(l.dau==NULL) l.dau=l.cuoi=p;
    else
    {
        l.cuoi->next=p;
        l.cuoi=p;
    }
}
void nhap(list &l)
{
    int x;
    node *p;
    do{
        cin>>x;
        if(x!=0)
        {
            p=taonode(x);
            themcuoi(l,p);
        }
    }while(x!=0);
}
void xuat(list l)
{
    node *p=l.dau;
    while(p!=NULL)
    {
        cout<<p->x<<" ";
        p=p->next;
    }
}
void sapxep(list &l)
{
    node *p1=l.dau,*p2;
    while(p1!=NULL)
    {
        p2=p1->next;
        while(p2!=NULL)
        {
            if(p2->x > p1->x) swap(p1->x,p2->x);
            p2=p2->next;
        }
        p1=p1->next;
    }
}
void xoadau(list &l)
{
    if(l.dau!=NULL)
    {
        node *p=l.dau;
        if(l.dau==l.cuoi)
        {
            l.dau=l.cuoi=NULL;
            delete p;
        }
        else
        {
            l.dau=l.dau->next;
            delete p;
        }
    }
}
void themdau(list &l,node *p)
{
    if(l.dau==NULL) l.dau=l.cuoi=p;
    else
    {
        p->next=l.dau;
        l.dau=p;
    }
}
void themsauQ(list &l,node *Q,node *p)
{
    if(Q==NULL) themdau(l,p);
    else if(Q==l.cuoi) themcuoi(l,p);
    else
    {
        p->next=Q->next;
        Q->next=p;
    }
}
void merge(list &l1,list &l2)
{
    node *p=l1.dau,*p1;
    while(l2.dau!=NULL && p!=NULL)
    {
        p1=taonode(l2.dau->x);
        themsauQ(l1,p,p1);
        xoadau(l2);
        if(p!=l1.cuoi) p=p->next;
        if(p!=l1.cuoi) p=p->next;
    }
}
void insert(list &l,int a)
{
    node *p1=taonode(a);
    node *p=l.dau,*p2=NULL;
    while(p!=NULL)
    {
        if(a>p->x)
        {
            if(p2==NULL) themdau(l,p1);
            else themsauQ(l,p2,p1);
            break;
        }
        p2=p;
        p=p->next;
    }
}
void main()
{
    list l1,l2;
    khoitao(l1);khoitao(l2);
    cout<<"nhap l1:\n";
    nhap(l1);
    cout<<"nhap l2:\n";
    nhap(l2);
    cout<<"\nxuat cac gia tri:\nl1: ";
    xuat(l1);
    cout<<"\nl2: ";
    xuat(l2);
    cout<<"\ncac gia tri l1,l2 sau khi merge:\n";
    merge(l1,l2);
    cout<<"l1: ";xuat(l1);
    cout<<"\nl2: ";xuat(l2);
    cout<<"\nsau khi sap xep giam danh sach l1:\n";
    sapxep(l1);
    xuat(l1);
    cout<<"\nnhap X=";
    int x;cin>>x;
    insert(l1,x);
    cout<<"l1: ";xuat(l1);
    cout<<endl;
    system("pause");
}

Tuesday, May 26, 2015

cấu trúc cây nhị phân tìm kiếm và các thao tác trên cây

cấu trúc cây nhị phân tìm kiếm và các thao tác trên cây. định nghĩa, và các thao tháo cần thiết phải có khi cài đặt 1 cay nhị phân tìm kiếm

Ðịnh nghĩa cây nhị phân tìm kiếm


Cây nhị phân
Bảo đảm nguyên tắc bố trí khoá tại mỗi nút:
Các nút trong cây trái nhỏ hơn nút hiện hành
Các nút trong cây phải lớn hơn nút hiện hành


Ưu điểm của cây nhị phân tìm kiếm


Nhờ trật tự bố trí khóa trên cây :
Định hướng được khi tìm kiếm
Cây gồm N phần tử :
Trường hợp tốt nhất h = log2N
Trường hợp xấu nhất h = Ln
Tình huống xảy ra trường hợp xấu nhất ?


Cấu trúc dữ liệu của cây nhị phân tìm kiếm


Cấu trúc dữ liệu của 1 nút
    typedef struct tagTNode
    {  
        int Key; //trường dữ liệu là 1 số nguyên
        struct tagTNode *pLeft;
        struct tagTNode *pRight;
    }TNode;
Cấu trúc dữ liệu của cây
    typedef TNode *TREE;

Các thao tác trên cây nhị phân tìm kiếm



Tạo 1 cây rỗng
Tạo 1 nút có trường Key bằng x
Thêm 1 nút vào cây nhị phân tìm kiếm
Xoá 1 nút có Key bằng x trên cây
Tìm 1 nút có khoá bằng x trên cây


Tạo cây rỗng


Cây rỗng -> địa chỉ nút gốc bằng NULL
    void CreateTree(TREE &T)
    {
        T=NULL;
    }

Tạo 1 nút có Key bằng x


TNode *CreateTNode(int x)
{
        TNode *p;
        p = new TNode; //cấp phát vùng nhớ động
        if(p==NULL)
            exit(1); // thoát
        else
        {
            p->key = x; //gán trường dữ liệu của nút = x
            p->pLeft = NULL;
            p->pRight = NULL;
        }
        return p;
}


Thêm một nút x


Rằng buộc: Sau khi thêm cây đảm bảo là cây nhị phân tìm kiếm.
int insertNode(TREE &T, Data X)
{   if(T)
    {   if(T->Key == X) return 0;
        if(T->Key > X) return insertNode(T->pLeft, X);
        else    return insertNode(T->pRight, X);}
        T   = new TNode;
        if(T == NULL)   return -1;
        T->Key  = X;
        T->pLeft =T->pRight = NULL;
    return 1;
}

Tìm nút có khoá bằng x (không dùng đệ quy)


TNode * searchNode(TREE Root,  Data x)
{       Node *p = Root;
        while (p != NULL)
        {   if(x == p->Key) return p;
            else  
            if(x < p->Key)  p = p->pLeft;
            else    p = p->pRight;
        }
        return NULL;
}

Tìm nút có khoá bằng x (dùng đệ quy)


TNode *SearchTNode(TREE T, int x)
{
    if(T!=NULL)
    {
        if(T->key==x)
            return T;
        else
            if(x>T->key)
                return SearchTNode(T->pRight,x);
            else
                return SearchTNode(T->pLeft,x);
    }
    return NULL;
}

Hủy 1 nút có khoá bằng X trên cây


Hủy 1 phần tử trên cây phải đảm bảo điều kiện ràng buộc của Cây nhị phân tìm kiếm
Có 3 trường hợp khi hủy 1 nút trên cây
TH1: X là nút lá
TH2: X chỉ có 1 cây con (cây con trái hoặc cây con phải)
TH3: X có đầy đủ 2 cây con
TH1: Ta xoá nút lá mà không ành hưởng đến các nút khác ttrên cây
TH2: Trước khi xoá x ta móc nối cha của X với con duy nhất cùa X.
TH3: Ta dùng cách xoá gián tiếp

Hủy 1 nút có 2 cây con


Ta dùng cách hủy gián tiếp, do X có 2 cây con
Thay vì hủy X ta tìm phần tử thế mạng Y. Nút Y có tối đa 1 cây con.
Thông tin lưu tại nút Y sẽ được chuyển lên lưu tại X.
Ta tiến hành xoá hủy nút Y (xoá Y giống 2 trường hợp đầu)
Cách tìm nút thế mạng Y cho X: Có 2 cách
 C1: Nút Y là nút có khoá nhỏ nhất (trái nhất) bên cây con phải X
C2: Nút Y là nút có khoá lớn nhất (phải nhất) bên cây con trái của X

Cài đặt thao tác xoá nút có trường Key = x


void DeleteNodeX1(TREE &T,int x)
{
    if(T!=NULL)
    {
        if(T->Key<x)    DeleteNodeX1(T->Right,x);
        else
        {
            if(T->Key>x)    DeleteNodeX1(T->Left,x);
            else  //tim thấy  Node có trường dữ liệu = x
            {   TNode *p;  
                p=T;
                if (T->Left==NULL)  T = T->Right;
                else
                {   if(T->Right==NULL)  T=T->Left;
                    else    ThayThe1(p, T->Right);// tìm bên cây con phải
                }
                delete p;
            }
        }
    }
    else    printf("Khong tim thay phan can xoa tu");
}

Hàm tìm phần tử thế mạng 


void ThayThe1(TREE &p, TREE &T)
{    if(T->Left!=NULL)
        ThayThe1(p,T->Left);
else
     {
        p->Key = T->Key;
        p=T;
        T=T->Right;
    }
}

cấu trúc cây trong lập trình c/c++

cấu trúc cây trong lập trình c/c++, cấu trúc cây rất quan trọng trong lập trình quản lý dữ liệu


Định Nghĩa Cây


Cây là một tập hợp T các phần tử (gọi là nút của cây), trong đó có một nút đặc biệt gọi là nút gốc, các nút còn lại được chia thành những tập rời nhau T1, T2, …,Tn theo quan hệ phân cấp, trong đó Ti cũng là 1 cây. Mỗi nút ở cấp i sẽ quản lý một số nút ở cấp i+1. Quan hệ này người ta gọi là quan hệ cha – con.

Một Số Khái Niệm


Bậc của một nút: là số cây con của nút đó .
Bậc của một cây: là bậc lớn nhất của các nút trong cây 
Nút gốc: là nút không có nút cha.
Nút lá: là nút có bậc bằng 0 .
Mức của một nút:
Mức (gốc (T) ) = 0.
Gọi T1, T2, T3, ... , Tn là các cây con của T0 : Mức (T1) = Mức (T2) = . . .  = Mức (Tn) = Mức (T0) + 1.
Độ dài đường đi từ gốc đến nút x: là số nhánh cần đi qua kể từ gốc đến x.

Một Số Tính Chất Của Cây Nhị Phân


Số nút nằm ở mức i  2i.
Số nút lá  2h-1, với h là chiều cao của cây.
Chiều cao của cây h  log2(N)
N = số nút trong cây
Số nút trong cây  2h-1.

Cấu Trúc Dữ Liệu Của Cây Nhị Phân


typedef struct tagTNode
{
Data Key; 
struct tagTNode *pLeft; struct tagTNode *pRight; 
}TNode;

typedef TNode *TREE;


Duyệt Cây Nhị Phân 


 Có 3 trình tự thăm gốc :
 Duyệt trước
 Duyệt giữa
 Duyệt sau
  Độ phức tạp O (log2(h))
    Trong đó h là chiều cao cây

Duyệt Trước 


void NLR(TREE Root)
{
if (Root != NULL)
{
<Xử lý Root>; //Xử lý tương ứng theo nhu cầu NLR(Root->pLeft);
NLR(Root->pRight);
}
}

Duyệt Giữa

void LNR(TREE Root)
{
if (Root != NULL)
{
LNR(Root->pLeft);
<Xử lý Root>; // Xử lý tương ứng theo nhu cầu 
LNR(Root->pRight);
}
}

Duyệt Sau

void LRN(TREE Root)
{
if (Root != NULL)
{
LRN(Root->pLeft);
LRN(Root->pRight);
<Xử lý Root>; // Xử lý tương ứng theo nhu cầu 
}
}

con trỏ và cấu trúc dữ liệu động

vấn đề về con trỏ và cấu trúc dữ liệu động trong lập trình c/c++. biến tĩnh, biến động, khai báo vùng nhớ,..

Biến Tĩnh


Được khai báo tường minh, có tên gọi
Tồn tại trong phạm vi khai báo
Được cấp phát trong stack
Kích thước không đổi => không tận dụng hiệu quả bộ nhớ
Ví dụ : int x,y;
char c;
float f[5];
Khi biết chắc nhu cầu sử dụng đối tượng trước khi thực sự xử lý : dùng biến không động


Ví Dụ Hạn Chế Của Biến Tinh


Tổ chức danh sách lớp học
Dùng mảng tĩnh :
typedef struct
{
    char ten[20];
int maso;
}Hocvien;
Hocvien danhsach[50];
Số lượng học viên <50 => lãng phí
Số lượng học viện > 50 => thiếu chỗ !

Biến Động 


Không được khai báo tường minh, không có tên gọi
Xin khi cần, giải phóng khi sử dụng xong
Được cấp phát trong heap
Linh động về kích thước
Vấn đề : biến động không có tên gọi tường minh, làm sao thao tác ?


Kiểu con trỏ


Kiểu con trỏ dùng lưu địa chỉ của một đối tượng dữ liệu khác.
Biến thuộc kiểu con trỏ Tp là biến mà giá trị của nó là địa chỉ cuả một vùng nhớ ứng với một biến kiểu T, hoặc là  giá trị NULL.
Khai báo trong  C :
typedef int *intpointer;
intpointer p;
Bản thân biến con trỏ là không động
Dùng biến con trỏ để lưu giữ điạ chỉ của biến động => truy xuất biến động thông qua biến con trỏ


Các thao tác trên kiểu con trỏ


Tạo ra một biến động và cho con trỏ ‘p’ chỉ đến nó:
void* malloc(size);
void* calloc(n,size);
new // hàm cấp phát bộ nhớ trong C++
Hủy một biến động do p chỉ đến :
Hàm free(p) huỷ vùng nhớ cấp phát bởi hàm malloc hoặc calloc do p trỏ tới
Hàm delete p huỷ vùng nhớ cấp phát bởi hàm new do p trỏ tới

Kiểu danh sách


Danh sách = { các phần tử có cùng kiểu}
Danh sách là một kiểu dữ liệu tuyến tính :
Mỗi phần tử có nhiều nhất 1 phần tử đứng trước
Mỗi phần tử có nhiều nhất 1 phần tử đứng sau
Là kiểu dữ liệu quen thuộc trong thực tế :
Danh sách học sinh
Danh mục sách trong thư viện
Danh bạ điện thoại
Danh sách các nhân viên trong công ty



Các hình thức tổ chức danh sách


 CTDL cho mỗi phần tử ?
 Thể hiện liên kết của các phần tử ?
 Hai hình thức cơ bản :
Liên kết ngầm : Mảng
Liên kết tường minh : Danh sách liên kết


Danh sách liên kết ngầm(mảng)


Mối liên hệ giữa các phần tử được thể hiện ngầm:
xi : phần tử thứ i trong danh sách
xi , xi+1 là kế cận trong danh sách
Phải lưu trữ liên tiếp các phần tử trong bộ nhớ
công thức xác định địa chỉ phần tử thứ i: address(i) = address(1) + (i-1)*sizeof(T)
Ưu điểm : Truy xuất trực tiếp, nhanh chóng
Nhược điểm:
 Sử dụng bộ nhớ kém hiệu quả
Kích thước cố định
Các thao tác thêm vào , loại bỏ không hiệu quả


Liên kết tuờng minh(Danh sánh liên kết)


CTDL cho một phần tử
Thông tin bản thân
Địa chỉ của phần tử kế trong danh sách
Mỗi phần tử là một biến động
Ưu điểm
+ Sử dụng hiệu quả bộ nhớ
+ Linh động về số lượng phần tử


Các loại danh sách liên kết


Danh sách liên kết đơn: Mỗi phần tử liên kết với phần tử đứng sau nó trong danh sách
Danh sách liên kết kép: Mỗi phần tử liên kết với phần tử đứng trước và sau nó trong danh sách
Danh sách liên Vòng: Phần tử cuối danh sách liên với phần tử đầu danh sách
Danh sách liên kết đơn vòng
Danh sách liên kết đôi vòng

Saturday, May 16, 2015

tính giá trị biểu thức bằng cây nhị phân

lập trình c++ trính giá trị biểu thức toán học gồm số nguyên, dấu ngoặc (), phép toán +-*/ bằng phương pháp cây nhị phân.
#include<iostream>
#include<string>
using namespace std;
typedef struct tagnode
{
     string s;
     struct tagnode *left;
     struct tagnode *right;
}node;
node *taonode(string s)
{
     node *p=new node;
     if(p==NULL)
     {
          cout<<"khong du bo nho";
          system("pause");
          exit(1);
     }
     p->s=s;
     p->left=p->right=NULL;
     return p;
}
typedef node *cay;
void taocay(cay &t)
{
     t=NULL;
}
int vitridau(string s,int j)
{
     for(int i=j+1;i<s.size();i++)
          if(s[i]=='+' || s[i]=='-' || s[i]=='*' || s[i]=='/' || s[i]=='(')
               return i;
     return -1;
}
int timngoac(string s,int i)
{
     int j,dem=1;
     for(j=i+1;j<s.size();j++)
     {
          if(s[j]=='(') dem++;
          else if(s[j]==')') dem--;
          if(dem==0) return j;
     }
     return -1;
}
void xulyngoac(string &s)
{
     if(s[0]=='(')
     {
          int i=timngoac(s,0);
          if(i==s.size()-1)
          {
               s.erase(0,1);
               s.erase(s.size()-1,1);
          }
     }
}
void doidau(string &c)
{
     int x=0;
     do{
          x=vitridau(c,x);
          if(x!=-1)
          {
               if(c[x]=='(') x=timngoac(c,x);
               else if(c[x]=='-' && c[x-1]!='*' && c[x-1]!='/') c[x]='+';
               else if(c[x]=='+' && c[x-1]!='*' && c[x-1]!='/') c[x]='-';
               //chỉ đổi dấu + thành - và dấu - thành cộng khi nó là dấu của 1 số hạng
               //nếu nó dấu của 1 thừa số thì dữ nguyên không thay đổi gì cả mặc dù
               //dấu của node của cây tức s[i] là dấu - vì dấu của thừa số không liên quan đến số hạng
          }
     }while(x!=-1);
}
node *setcay(string s)
{
     xulyngoac(s);
     node *p;
     int k,j,x;
     string a,b,c;
     int i=vitridau(s,0);//tìm vị trí dấu đầu tiên trong biểu thức, có 2 trường hợp, có dấu và không có dấu
     if(s[0]=='(') i=0;
     if(i==-1)// trường hợp không có dấu
     {
          p=taonode(s);
          return p;
     }
     else//trường hợp có dấu, có 3 trường hợp nhỏ
     {
          if(s[i]=='+' || s[i]=='-')// dấu + hoặc -
          {
               a=s[i];
               p=taonode(a);
               b=s.substr(0,i);
               xulyngoac(b);
               c=s.substr(i+1,s.size()-i-1);
               xulyngoac(c);
               //đổi dấu các số hạng phía sau nếu s[i] là dấu -
               if(s[i]=='-') doidau(c);
               p->left=setcay(b);
               p->right=setcay(c);
          }
          else if(s[i]=='*' || s[i]=='/')//dấu * hoặc /
          {
               k=i;
               //tìm vị trí dấu + hoặc - phía sau dấu ngoặc nhưng nằm ngoài dấu ngoặc
               do{
                    k=vitridau(s,k);
                    if(k!=-1)
                    {
                         if(s[k]=='(') k=timngoac(s,k);
                         if(k>0 && (s[k]=='+' || s[k]=='-') && (s[k-1]!='*' && s[k-1]!='/')) break;
                    }
               }while(k!=-1);
               if(k==-1)//nếu không có thì node sẽ là dấu * hoặc / tại vị trí i ban đầu
               {
                    a=s[i];
                    p=taonode(a);
                    b=s.substr(0,i);
                    xulyngoac(b);
                    c=s.substr(i+1,s.size()-i-1);
                    xulyngoac(c);
                    p->left=setcay(b);
                    p->right=setcay(c);
               }
               else//nếu tìm thấy thì node là dấu tìm thấy
               {
                    a=s[k];
                    p=taonode(a);
                    b=s.substr(0,k);
                    xulyngoac(b);
                    c=s.substr(k+1,s.size()-k-1);
                    xulyngoac(c);
                    //doi dau +-
                    if(s[k]=='-') doidau(c);
                    p->left=setcay(b);
                    p->right=setcay(c);
               }
          }
          else if(s[i]=='(')//dấu mở ngoặc (
          {
               j=timngoac(s,i);//tìm vị trí dấu đóng ngoặc
               
               if(s[j+1]=='+' || s[j+1]=='-')//sau dấu đóng ngoặc là dấu + hoặc - thì node là dấu + hoặc -
               {
                    a=s[j+1];
                    p=taonode(a);
                    b=s.substr(0,j+1);
                    xulyngoac(b);
                    c=s.substr(j+2,s.size()-j-2);
                    xulyngoac(c);
                    //doi dau +-
                    if(s[j+1]=='-') doidau(c);
                    p->left=setcay(b);
                    p->right=setcay(c);
               }
               else if(s[j+1]=='*' || s[j+1]=='/')//nếu sau đóng ngoặc là * hoặc /
               {
                    k=j+1;
                    //tiếp tục tìm dấu + - phía sau nó mà nằm ngoài tất cả dấu ngoặc
                    do{
                         k=vitridau(s,k);
                         if(k!=-1)
                         {
                              if(s[k]=='(') k=timngoac(s,k);
                              if(k>0 && (s[k]=='+' || s[k]=='-') && (s[k-1]!='*' && s[k-1]!='/')) break;
                         }
                    }while(k!=-1);
                    if(k==-1)//nếu không tìm thấy thì node là dấu */ tại trí j+1
                    {
                         a=s[j+1];
                         p=taonode(a);
                         b=s.substr(0,j+1);
                         xulyngoac(b);
                         c=s.substr(j+2,s.size()-j-2);
                         xulyngoac(c);
                         p->left=setcay(b);
                         p->right=setcay(c);
                    }
                    else//nếu tìm thấy thì node là dấu tìm thấy
                    {
                         a=s[k];
                         p=taonode(a);
                         b=s.substr(0,k);
                         xulyngoac(b);
                         c=s.substr(k+1,s.size()-k-1);
                         xulyngoac(c);
                         //doi dau +-
                         if(s[j+1]=='-') doidau(c);
                         p->left=setcay(b);
                         p->right=setcay(c);
                    }
               }
          }
     }
     return p;
}
long atol(string s)
{
     long x=0,d=1;
     int j=0,k=0;
     if(s[0]=='+' || s[0]=='-')
     {
          j=1;
          if(s[0]=='-') k=1;
     }
     for(int i=s.size()-1;i>=j;i--)
     {
          switch(s[i])
          {
          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;
     }
     if(k==0)return x;
     return -x;
}
long tinh(cay t)
{
     long x;
     if(t)
     {
          if(t->s=="+") return tinh(t->left)+tinh(t->right);
          else if(t->s=="-") return tinh(t->left)-tinh(t->right);
          else if(t->s=="*") return tinh(t->left)*tinh(t->right);
          else if(t->s=="/") return tinh(t->left)/tinh(t->right);
          else return atol(t->s);
     }
     return 0;
}
void main()
{
     cay t;
     taocay(t);
     string s;
     cout<<"nhap bieu thuc toan hoc cua cac so nguyen duong:\n";
     getline(cin,s);
     t=setcay(s);
     cout<<"gia tri bieu thuc = "<<tinh(t)<<endl;
     system("pause");
}

Thursday, May 14, 2015

cộng trừ nhân chia số nguyên lớn không giới hạn

viết chương trình định nghĩa kiểu số nguyên lớn không giới hạn, lập trình thực hiện các phép toán công (+) trừ (-) nhân (*) chia (/) các số nguyên lớn đó. thông thường ta thấy các kiểu float, int có giới hạn của nó, khi vượt quá giớ hạn thì báo lỗi hoặc cho kết quả sai, sau khi học qua danh sách liên kết thì t có thực hiện bài tập giải quyết số nguyên lớn không giới hạn, định nghĩa và thiết kế thuật toán công trừ nhân chia các số nguyên lớn đó. dưới đây là code của chương trình đó, tuy nhiên t không viết chú thích nên có phần khó. dã học qua danh sách liên kết và năm rõ về nó thì sẽ dễ đọc code hơn. mỗi node trong danh sách sẽ lưu 1 chữ só của số nguyên lớn, 1 biến kiểu char trong danh sách để lưu dấu ccủa số là dương hay âm. giá trị của mỗi node trong danh sách theo thứ tự từ đầu đến cuối là giá trị các chữ số của số nguyên lớn. do đó khi công trừ nhân chia, ta duyệt từng node trong danh sách là tiến hành tính toán trên đó, cộng trừ nhân thì thực hiện từ cuối lên đầu, còn chia thì thực hiện duyệt từ đầu đến cuối
#include<iostream>
#include<string>
#include<Windows.h>
using namespace std;
typedef struct tagnode
{
    int x;
    struct tagnode *next;
    struct tagnode *pre;
}node;
typedef struct tagsolon
{
    char c;
    node *dau;
    node *cuoi;
}solon;
void xuat(solon n);
void taosolon(solon &n);
node *taonode(int x);
void themdau(solon &n,node *p);
void nhap(solon &n);
void cong(solon n1,solon n2,solon &n);
void tru(solon n1,solon n2,solon &n);
int sosanh(solon n1,solon n2);
void nhan(solon n1,solon n2,solon &n);
void nhan1so(solon n1,int x,solon &n);
void themcuoi(solon &n,node *p);
void xoa(solon &n);
void xoatruocQ(solon &n,node *Q);
void xoacuoi(solon &n);
void chia(solon n1,solon n2,solon &n);
void xuly(solon &n);

void main()
{
    solon n,n1,n2;
    taosolon(n);taosolon(n1);taosolon(n2);
    cout<<"nhap 2 so nguyen:\n";
    cout<<"a=";nhap(n1);
    cout<<"b=";nhap(n2);
    cout<<"\n1.cong."
        <<"\n2.tru."
        <<"\n3.nhan."
        <<"\n4.chia.\n\n";
    int k;
    cin>>k;
    switch(k)
    {
    case 1:cong(n1,n2,n);cout<<"a+b = ";xuat(n);cout<<endl;break;
    case 2:tru(n1,n2,n);cout<<"a-b = ";xuat(n);cout<<endl;break;
    case 3:nhan(n1,n2,n);cout<<"a*b = ";xuat(n);cout<<endl;break;
    case 4:chia(n1,n2,n);break;
    }
    system("pause");
}


void chia(solon n1,solon n2,solon &n)
{
    if(n1.c==n2.c) n.c='+';
    else n.c='-';
    int q=sosanh(n1,n2);
    if(q<0)
    {
        cout<<"ket qua = 0 \ndu ";xuat(n1);
    }
    else if(q==0) cout<<"ket qua = 1";
    else
    {
        int i;
        solon a;taosolon(a);
        solon b;taosolon(b);
        solon c;taosolon(c);
        node *p,*p2,*p1;
        p1=n1.dau;
        p2=n2.dau;
        while(p2!=NULL)
        {
            p=taonode(p1->x);
            themcuoi(a,p);
            p1=p1->next;
            p2=p2->next;
        }
        while(p1!=NULL)
        {
            q=sosanh(a,n2);
            if(q<0)
            {
                p=taonode(0);
                themcuoi(n,p);
                p=taonode(p1->x);
                themcuoi(a,p);
            }
            else if(q==0)
            {
                p=taonode(1);
                themcuoi(n,p);
                xoa(a);
                p=taonode(p1->x);
                themcuoi(a,p);
            }
            else
            {
                for(i=1;i<=9;i++)
                {
                    xoa(b);
                    nhan1so(n2,i,b);
                    q=sosanh(a,b);
                    if(q<0)
                    {
                        xoa(b);
                        nhan1so(n2,i-1,b);
                        break;
                    }
                }
                i--;
                p=taonode(i);
                themcuoi(n,p);
                xoa(c);
                tru(a,b,c);
                xoa(a);
                p2=c.dau;
                while(p2!=NULL)
                {
                    p=taonode(p2->x);
                    themcuoi(a,p);
                    p2=p2->next;
                }
                p=taonode(p1->x);
                themcuoi(a,p);
            }
            if(p1!=NULL)p1=p1->next;
        }
        // thuc hien 1 lan nua
        q=sosanh(a,n2);
        if(q<0)
        {
            p=taonode(0);
            themcuoi(n,p);
        }
        else if(q==0)
        {
            p=taonode(1);
            themcuoi(n,p);
        }
        else
        {
            for(i=1;i<=9;i++)
            {
                xoa(b);
                nhan1so(n2,i,b);
                q=sosanh(a,b);
                if(q<0)
                {
                    xoa(b);
                    nhan1so(n2,i-1,b);
                    break;
                }
            }
            i--;
            p=taonode(i);
            themcuoi(n,p);
            xoa(c);
            tru(a,b,c);
            xoa(a);
            p2=c.dau;
            while(p2!=NULL)
            {
                p=taonode(p2->x);
                themcuoi(a,p);
                p2=p2->next;
            }
        }
        if(p1!=NULL)p1=p1->next;
        //end
        xuly(n);xuly(a);
        cout<<"a/b = ";xuat(n);cout<<endl;
        if(a.dau!=NULL)
        {
            cout<<"du ";
            xuat(a);
            cout<<endl;
        }
    }
}
void xoatruocQ(solon &n,node *Q)
{
    if(Q==NULL) xoacuoi(n);
    else
    {
        node *p=Q->pre;
        if(p!=NULL)
        {
            if(p==n.dau)
            {
                n.dau=Q;
                n.dau->pre=NULL;
                delete p;
            }
            else
            {
                p->pre->next=Q;
                Q->pre=p->pre;
                delete p;
            }
        }
    }
}
void xuly(solon &n)
{
    node *p=n.dau;
    while(p!=NULL && p->x==0)
    {
        p=p->next;
        xoatruocQ(n,p);
    }
}
void nhan(solon n1,solon n2,solon &n)
{
    node *p,*p1,*p2;
    long long i,dem=0;
    solon a;taosolon(a);
    solon b;taosolon(b);
    p=n2.cuoi;
    while(p!=NULL)
    {
        xoa(a);
        nhan1so(n1,p->x,a);
        for(i=0;i<dem;i++)
        {
            p1=taonode(0);
            themcuoi(a,p1);
        }
        xoa(b);
        p2=n.cuoi;
        while(p2!=NULL)
        {
            p1=taonode(p2->x);
            themdau(b,p1);
            p2=p2->pre;
        }
        xoa(n);
        cong(a,b,n);
        p=p->pre;
        dem++;
    }
    if(n1.c==n2.c) n.c='+';
    else n.c='-';
    xuly(n);
}
void xoa(solon &n)
{
    while(n.dau!=NULL) xoacuoi(n);
}
void xoacuoi(solon &n)
{
    node *p=n.cuoi;
    if(p!=NULL)
    {
        if(n.dau==n.cuoi)
        {
            n.dau=n.cuoi=NULL;
            delete p;
        }
        else
        {
            n.cuoi=p->pre;
            n.cuoi->next=NULL;
            delete p;
        }
    }
}
void themcuoi(solon &n,node *p)
{
    if(n.dau==NULL)n.dau=n.cuoi=p;
    else
    {
        n.cuoi->next=p;
        p->pre=n.cuoi;
        n.cuoi=p;
    }
}
void nhan1so(solon n1,int x,solon &n)
{
    node *p1,*p;
    int k,m=0;
    p1=n1.cuoi;
    while(p1!=NULL)
    {
        k=p1->x*x+m;
        if(k>=10)
        {
            m=k/10;
            k=k%10;
        }
        else m=0;
        p=taonode(k);
        themdau(n,p);
        p1=p1->pre;
    }
    if(m>0)
    {
        p=taonode(m);
        themdau(n,p);
    }
}
void tru(solon n1,solon n2,solon &n)
{
    int q=sosanh(n1,n2);
    int k,m;
    node *p,*p1,*p2;
    if(q==0) return;
    if(n1.c=='+' && n2.c=='+')
    {
        if(q>0)
        {
            m=0;n.c='+';
            p1=n1.cuoi;p2=n2.cuoi;
            while(p1!=NULL && p2!=NULL)
            {
                if(p1->x < (p2->x + m))
                {
                    k=10+p1->x-p2->x-m;
                    m=1;
                }
                else
                {
                    k=p1->x-p2->x-m;
                    m=0;
                }
                p=taonode(k);
                themdau(n,p);
                p1=p1->pre;
                p2=p2->pre;
            }
            while(p1!=NULL)
            {
                if(p1->x < m)
                {
                    k=10+p1->x-m;
                    m=1;
                }
                else
                {
                    k=p1->x-m;
                    m=0;
                }
                p=taonode(k);
                themdau(n,p);
                p1=p1->pre;
            }
        }
        else
        {
            m=0;n.c='-';
            p1=n1.cuoi;p2=n2.cuoi;
            while(p1!=NULL && p2!=NULL)
            {
                if(p2->x < (p1->x + m))
                {
                    k=10+p2->x-p1->x-m;
                    m=1;
                }
                else
                {
                    k=p2->x-p1->x-m;
                    m=0;
                }
                p=taonode(k);
                themdau(n,p);
                p2=p2->pre;
                p1=p1->pre;
            }
            while(p2!=NULL)
            {
                if(p2->x < m)
                {
                    k=10+p2->x-m;
                    m=1;
                }
                else
                {
                    k=p2->x-m;
                    m=0;
                }
                p=taonode(k);
                themdau(n,p);
                p2=p2->pre;
            }
        }
    }
    else if(n1.c=='-' && n2.c=='-')
    {
        if(q>0)
        {
            m=0;n.c='-';
            p1=n1.cuoi;p2=n2.cuoi;
            while(p1!=NULL && p2!=NULL)
            {
                if(p1->x < (p2->x + m))
                {
                    k=10+p1->x-p2->x-m;
                    m=1;
                }
                else
                {
                    k=p1->x-p2->x-m;
                    m=0;
                }
                p=taonode(k);
                themdau(n,p);
                p1=p1->pre;
                p2=p2->pre;
            }
            while(p1!=NULL)
            {
                if(p1->x < m)
                {
                    k=10+p1->x-m;
                    m=1;
                }
                else
                {
                    k=p1->x-m;
                    m=0;
                }
                p=taonode(k);
                themdau(n,p);
                p1=p1->pre;
            }
        }
        else
        {
            m=0;n.c='+';
            p1=n1.cuoi;p2=n2.cuoi;
            while(p1!=NULL && p2!=NULL)
            {
                if(p2->x < (p1->x + m))
                {
                    k=10+p2->x-p1->x-m;
                    m=1;
                }
                else
                {
                    k=p2->x-p1->x-m;
                    m=0;
                }
                p=taonode(k);
                themdau(n,p);
                p2=p2->pre;
                p1=p1->pre;
            }
            while(p2!=NULL)
            {
                if(p2->x < m)
                {
                    k=10+p2->x-m;
                    m=1;
                }
                else
                {
                    k=p2->x-m;
                    m=0;
                }
                p=taonode(k);
                themdau(n,p);
                p2=p2->pre;
            }
        }
    }
    else if(n1.c=='+' && n2.c=='-')
    {
        n2.c='+';
        cong(n1,n2,n);
    }
    else if(n1.c=='-' && n2.c=='+')
    {
        n2.c='-';
        cong(n1,n2,n);
    }
    xuly(n);
}
void cong(solon n1,solon n2,solon &n)
{
    if(n1.c==n2.c)
    {
        n.c=n1.c;
        int k,m=0;
        node *p1=n1.cuoi,*p2=n2.cuoi,*p;
        while(p1!=NULL && p2!=NULL)
        {
            k=p1->x+p2->x+m;
            if(k>=10)
            {
                m=k/10;
                k=k%10;
            }
            else m=0;
            p=taonode(k);
            themdau(n,p);
            p1=p1->pre;
            p2=p2->pre;
        }
        while(p1!=NULL)
        {
            k=p1->x+m;
            if(k>=10)
            {
                m=k/10;
                k=k%10;
            }
            else m=0;
            p=taonode(k);
            themdau(n,p);
            p1=p1->pre;
        }
        while(p1!=NULL)
        {
            k=p1->x+m;
            if(k>=10)
            {
                m=k/10;
                k=k%10;
            }
            else m=0;
            p=taonode(k);
            themdau(n,p);
            p1=p1->pre;
        }
        if(m>0)
        {
            p=taonode(m);
            themdau(n,p);
        }

    }
    else if(n1.c=='+' && n2.c=='-')
    {
        n2.c='+';
        tru(n1,n2,n);
    }
    else
    {
        n1.c='+';
        tru(n2,n1,n);
    }
    xuly(n);
}
int sosanh(solon n1,solon n2)
{
    node *p1=n1.cuoi,*p2=n2.cuoi;
    while(p1!=NULL && p2!=NULL)
    {
        p1=p1->pre;
        p2=p2->pre;
    }
    if(p1==NULL && p2!=NULL) return -1;
    if(p1!=NULL && p2==NULL) return 1;
    if(p1==NULL && p2==NULL)
    {
        p1=n1.dau;
        p2=n2.dau;
        while(p1!=NULL && p2!=NULL)
        {
            if(p1->x > p2->x) return 1;
            if(p1->x < p2->x) return -1;
            p1=p1->next;
            p2=p2->next;
        }
        return 0;
    }
}
void xuat(solon n)
{
    node *p=n.dau;
    if(p==NULL)
    {
        cout<<0;
        return;
    }
    if(p!=NULL && n.c=='-') cout<<n.c;
    while(p!=NULL)
    {
        cout<<p->x;
        p=p->next;
    }
}
void taosolon(solon &n)
{
    n.c='+';
    n.dau=n.cuoi=NULL;
}
node *taonode(int x)
{
    node *p=new node;
    if(p==NULL) exit(1);
    p->x=x;
    p->next=p->pre=NULL;
    return p;
}
void themdau(solon &n,node *p)
{
    if(n.dau==NULL) n.dau=n.cuoi=p;
    else
    {
        p->next=n.dau;
        n.dau->pre=p;
        n.dau=p;
    }
}
void nhap(solon &n)
{
    string s;
    node *p;
    long long i,j=0;
    getline(cin,s);
    if(s[0]=='-')
    {
        n.c='-';
        j=1;
    }
    else if(s[0]=='+')
    {
        n.c='+';
        j=1;
    }
    else n.c='+';
    for(i=s.size()-1;i>=j;i--)
    {
        switch(s[i])
        {
        case '0':p=taonode(0);break;
        case '1':p=taonode(1);break;
        case '2':p=taonode(2);break;
        case '3':p=taonode(3);break;
        case '4':p=taonode(4);break;
        case '5':p=taonode(5);break;
        case '6':p=taonode(6);break;
        case '7':p=taonode(7);break;
        case '8':p=taonode(8);break;
        case '9':p=taonode(9);break;
        }
        themdau(n,p);
    }
}
trên đây là toàn bộ code của chương trình cộng trừ nhân chia số nguyên lớn không giới hạn. code hơi dài, t mất 10 tiếng đồng hồ để suy nghĩ cách làm và cài đặt code, pro đọc qua thấy hay thì like và cải tiến code hoặc gởi form liên hệ code hay hơn để t học hỏi nhé!

cộng trừ nhân chia đa thức bậc n bất kỳ

viết chương trình c/c++ thực hiện định nghĩa đa thức bậ n bất kỳ và cộng trừ nhân chia trên đa thức. cách làm của Toàn dưới đây là dùng danh sách liên kết đôi để làm. mỗi node sẽ lưu 1 số hạng gồm 2 thông tin là hệ số và số mũ, ngoài thông tin còn có 2 con trỏ của danh sách liên kết. cộng trừ nhân chia đa thức theo kiểu này gây khó khăn cho lập trình nhưng chương trình được tối ưu và chạy nhanh.
#include<iostream>
using namespace std;
typedef struct tagnode
{
    float heso,somu;
    struct tagnode *next,*pre;
}node;
node *taonode(float heso,float somu)
{
    node *p=new node;
    if(p==NULL) exit(1);
    p->heso=heso;
    p->somu=somu;
    p->next=p->pre=NULL;
    return p;
}
typedef struct tagdathuc
{
    node*dau,*cuoi;
}dathuc;
void taodathuc(dathuc &l)
{
    l.dau=l.cuoi=NULL;
}
void themcuoi(dathuc &l,node *p)
{
    if(l.dau==NULL) l.dau=l.cuoi=p;
    else
    {
        l.cuoi->next=p;
        p->pre=l.cuoi;
        l.cuoi=p;
    }
}
void nhap(dathuc &l)
{
    node *p;
    float heso,somu;
    cout<<"nhap so da thuc, ket thuc khi nhap he so = 0\n";
    do{
        cout<<"he so = ";cin>>heso;
        if(heso!=0)
        {
            cout<<"so mu = ";cin>>somu;
            p=taonode(heso,somu);
            themcuoi(l,p);
        }
        cout<<endl;
    }while(heso!=0);
}
void xuat(dathuc l)
{
    node *p=l.dau;
    if(p==NULL)
    {
        cout<<0;
        return;
    }
    while(p!=NULL)
    {
        if(p==l.dau)
        {
            if(p->somu==0) cout<<p->heso;
            else if(fabs(p->heso)!=1 && p->somu!=1) cout<<p->heso<<"X^"<<p->somu;
            else if(fabs(p->heso)!=1 && p->somu==1) cout<<p->heso<<"X";
            else if(fabs(p->heso)==1 && p->somu!=1) cout<<(p->heso==1?"X^":"-X^")<<p->somu;
            else cout<<(p->heso==1?"X":"-X");
        }
        else
        {
            if(p->somu==0) cout<<(p->heso<0?" - ":" + ")<<fabs(p->heso);
            else if(fabs(p->heso)!=1 && p->somu!=1) cout<<(p->heso<0?" - ":" + ")<<fabs(p->heso)<<"X^"<<p->somu;
            else if(fabs(p->heso)!=1 && p->somu==1) cout<<(p->heso<0?" - ":" + ")<<fabs(p->heso)<<"X";
            else if(fabs(p->heso)==1 && p->somu!=1) cout<<(p->heso==1?" + X^":" - X^")<<p->somu;
            else cout<<(p->heso==1?" + X":" - X");
        }
        p=p->next;
    }
}
void sapxep(dathuc &l)
{
    node *p1=l.dau,*p2;
    while(p1!=NULL)
    {
        p2=p1->next;
        while(p2!=NULL)
        {
            if(p2->somu>p1->somu)
            {
                swap(p1->heso,p2->heso);
                swap(p1->somu,p2->somu);
            }
            p2=p2->next;
        }
        p1=p1->next;
    }
}
void xoatruocQ(dathuc &l,node *Q)
{
    node *p;
    if(Q==NULL)
    {
        p=l.cuoi;
        if(l.dau==l.cuoi)
        {
            l.dau=l.cuoi=NULL;
            delete p;
        }
        else if(p!=NULL)
        {
            l.cuoi=l.cuoi->pre;
            l.cuoi->next=NULL;
            delete p;
        }
    }
    else
    {
        p=Q->pre;
        if(p!=NULL)
        {
            if(p==l.dau)
            {
                l.dau=l.dau->next;
                l.dau->pre=NULL;
                delete p;
            }
            else
            {
                p->pre->next=Q;
                Q->pre=p->pre;
                delete p;
            }
        }
    }
}
void rutgon(dathuc &l)
{
    node *p1=l.dau,*p2;
    while(p1!=NULL)
    {
        p2=p1->next;
        while(p2!=NULL)
        {
            if(p2->somu==p1->somu)
            {
                p1->heso+=p2->heso;
                p2=p2->next;
                xoatruocQ(l,p2);
            }
            else p2=p2->next;
        }
        p1=p1->next;
    }
}
void themtruocQ(dathuc &l,node *Q,node *p)
{
    if(Q==l.dau)
    {
        l.dau->pre=p;
        p->next=l.dau;
        l.dau=p;
    }
    else
    {
        p->pre=Q->pre;
        p->next=Q;
        Q->pre->next=p;
        Q->pre=p;
    }
}
void insert(dathuc &l,node *p)
{
    node *p1=l.dau;
    while(p1!=NULL && p1->somu > p->somu) p1=p1->next;
    if(p1!=NULL)
    {
        if(p1->somu == p->somu) p1->heso += p->heso;
        else themtruocQ(l,p1,p);
    }
    else themcuoi(l,p);
}
void xuly(dathuc &l)
{
    node *p=l.dau;
    while(p!=NULL)
    {
        if(p->heso==0)
        {
            p=p->next;
            xoatruocQ(l,p);
        }
        else p=p->next;
    }
}
int cong(dathuc l1,dathuc l2,dathuc &l)
{
    node *p=l1.dau,*a;
    while(p!=NULL)
    {
        a=taonode(p->heso,p->somu);
        themcuoi(l,a);
        p=p->next;
    }
    p=l2.dau;
    while(p!=NULL)
    {
        a=taonode(p->heso,p->somu);
        insert(l,a);
        xuly(l);
        p=p->next;
    }
    xuly(l);
    if(l.dau==NULL) return 0;
    return 1;
}
int tru(dathuc l1,dathuc l2,dathuc &l)
{
    node *p=l2.dau;
    while(p!=NULL)
    {
        p->heso=-p->heso;
        p=p->next;
    }
    cong(l1,l2,l);
    p=l2.dau;
    while(p!=NULL)
    {
        p->heso=-p->heso;
        p=p->next;
    }
    if(l.dau==NULL) return 0;
    return 1;
}
int nhan(dathuc l1,dathuc l2,dathuc &l)
{
    node *p,*p1,*p2;
    p2=l2.dau;
    while(p2!=NULL)
    {
        p1=l1.dau;
        while(p1!=NULL)
        {
            p=taonode(p2->heso*p1->heso,p2->somu+p1->somu);
            insert(l,p);
            p1=p1->next;
        }
        p2=p2->next;
    }
    xuly(l);
    if(l.dau==NULL) return 0;
    return 1;
}
void xoacuoi(dathuc &l)
{
    node *p=l.cuoi;
    if(p==NULL) exit(1);
    if(l.dau==l.cuoi)
    {
        l.dau=l.cuoi=NULL;
        delete p;
    }
    else
    {
        l.cuoi=p->pre;
        l.cuoi->next=NULL;
        delete p;
    }
}
void xoa(dathuc &l)
{
    while(l.dau!=NULL) xoacuoi(l);
}
void chia(dathuc l1,dathuc l2)
{
    node *p,*p1;
    dathuc a,b,du;
    taodathuc(a);taodathuc(b);taodathuc(du);
    p1=l1.dau;
    while(p1!=NULL)
    {
        p=taonode(p1->heso,p1->somu);
        themcuoi(du,p);
        p1=p1->next;
    }
    while(du.dau!=NULL && du.dau->somu >= l2.dau->somu)
    {
        p=taonode(du.dau->heso / l2.dau->heso,du.dau->somu - l2.dau->somu);
        themcuoi(a,p);
        xoa(b);
        if(nhan(l2,a,b)==0) break;
        xoa(du);
        if(tru(l1,b,du)==0) break;
    }
    xuat(a);
    if(du.dau!=NULL)
    {
        cout<<"\n du ";
        xuat(du);
    }
}
void main()
{
    dathuc l1,l2,l;
    taodathuc(l1);taodathuc(l2);taodathuc(l);
    nhap(l1);nhap(l2);
    rutgon(l1);sapxep(l1);
    cout<<"\nda thuc 1 = ";xuat(l1);cout<<endl;
    rutgon(l2);sapxep(l2);
    cout<<"\nda thuc 2 = ";xuat(l2);cout<<endl;
    int k;
    cout<<"\n\n1.cong da thuc 1+2"
        <<"\n2.tru da thuc 1-2"
        <<"\n3.nhan da thuc 1*2"
        <<"\n4.chia da thuc 1/2\n";
    cin>>k;
    cout<<"ket qua = ";
    switch(k)
    {
    case 1:cong(l1,l2,l);xuat(l);break;
    case 2:tru(l1,l2,l);xuat(l);break;
    case 3:nhan(l1,l2,l);xuat(l);break;
    case 4:chia(l1,l2);break;
    }
    cout<<endl;
    system("pause");
}
trên đây là toàn bộ code của chương trình c/c++ cộng trù nhân chia đa thức bậc n bất kỳ bằng phương pháp sử dụng danh sách liên kết đôi.

Thursday, April 30, 2015

danh sách liên kết kép

danh sách liên kết kép, định nghĩa struct và các hàm thành phần có trong danh sách kép

Sunday, April 26, 2015

danh sách liên kết đơn

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.

sắp xếp trộn run sắp xếp ngoại

 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

Sunday, April 5, 2015

thuật toán sắp xếp radix sort



Radix Sort là một thuật toán tiếp cận theo một hướng hoàn toàn khác.
Nếu như trong các thuật toán khác, cơ sở để sắp xếp luôn là việc so sánh giá trị của 2 phần tử thì Radix Sort lại dựa trên nguyên tắc phân loại thư của bưu điện. Vì lý do đó Radix Sort còn có tên là Postman’s Sort.
Radix Sort không hề quan tâm đến việc so sánh giá trị của phần tử mà bản thân việc phân loại và trình tự phân loại sẽ tạo ra thứ tự cho các phần tử.
Mô phỏng lại qui trình trên, để sắp xếp dãy a1, a2, ..., an, giải thuật Radix Sort thực hiện như sau:
Trước tiên, ta có thể giả sử mỗi phần tử ai trong dãy a1, a2, ..., an là một số nguyên có tối đa m chữ số.

thuật toán merge sort - sắp xếp trộn




Giải thuật Merge sort sắp xếp dãy a1, a2, ..., an dựa trên nhận xét sau:
Mỗi dãy a1, a2, ..., an bất kỳ là một tập hợp các dãy con liên tiếp mà mỗi dãy con đều đã có thứ tự.
Ví dụ: dãy 12, 2, 8, 5, 1, 6, 4, 15 có thể coi như gồm 5 dãy con không giảm (12); (2, 8); (5); (1, 6); (4, 15).
Dãy đã có thứ tự coi như có 1 dãy con.
Hướng tiếp cận: tìm cách làm giảm số dãy con không giảm của dãy ban đầu.
Bước 1 : // Chuẩn bị
k = 1; // k là chiều dài của dãy con trong bước hiện hành
Bước 2 :
Tách dãy a0, a1, ., an-1 thành 2 dãy b, c theo nguyên tắc luân phiên từng nhóm k phần tử:
b = a0, ., ak, a2k, ., a3k, .
c = ak+1, ., a2k+1, a3k+1, .
Bước 3 :

thuật toán quick sort - sắp xếp nhanh

Giải thuật QuickSort sắp xếp dãy a1, a2 ..., aN dựa trên việc phân hoạch dãy ban đầu thành 3 phần :

Phần 1: Gồm các phần tử  có giá trị bé hơn x
Phần 2: Gồm các phần tử  có giá trị bằng  x
Phần 3: Gồm các phần tử  có giá trị lớn hơn x
với x là giá trị của một phần tử  tùy ý trong dãy ban đầu.
Sau khi thực hiện phân hoạch, dãy ban đầu được phân thành 3 đoạn:
1. ak  ≤ x , với k = 1 .. j
2. ak  = x , với k =  j+1 .. i-1
3. ak   x , với k =  i..N

thuật toán heap sort - sắp xếp vun đống, (cây)

thuật toán heap sort - sắp xếp vun đống, (cây)


Heap Sort tận dụng được các phép so sánh ở bước i-1 mà thuật toán sắp xếp chọn trực tiếp không tận dụng được
Để làm được điều này Heap sort thao tác dựa trên cây.
Ở cây trên, phần tử ở mức i chính là phần tử lớn trong cặp phần tử ở mức i +1, do đó phần tử ở nút gốc là phần tử lớn nhất.
Nếu loại bỏ gốc ra khỏi cây, thì việc cập  nhật cây chỉ xảy ra trên những nhánh liên quan đến phần tử mới loại bỏ, còn các nhánh khác thì bảo toàn.
Bước kế tiếp có thể sử dụng lại kết quả so sánh của bước hiện tại.
Vì thế độ phức tạp của thuật toán O(nlog2n)

thuật toán shell sort - cải tiến của chèn trực tiếp

thuật toán shell sort - cải tiến của chèn trực tiếp




shell sort là Cải tiến của phương pháp chèn trực tiếp
Ý tưởng:
Phân hoạch dãy thành các dãy con
Sắp xếp các dãy con theo phương pháp chèn trực tiếp
Dùng phương pháp chèn trực tiếp sắp xếp lại cả dãy.
Phân chia dãy ban đầu thành những dãy con gồm các phần tử  ở cách nhau h vị trí
Dãy ban đầu : a1, a2, ..., an được xem như sự xen kẽ của các dãy con sau :
Dãy con thứ nhất : a1 ah+1 a2h+1 ...
Dãy con thứ  hai  : a2 ah+2 a2h+2 ...
....

thuật toán binary insertion sort - chèn nhị phân

thuật toán binary insertion sort - chèn nhị phân

void BInsertionSort(int a[],int n )
{
int l,r,m,i;
int x;//lưu giá trị a[i] tránh bị ghi đè khi dời chỗ các phần tử.
for(int i=1 ; i<n ; i++)
{
x = a[i]; l = 0;
r = i-1;
while(l<=r) // tìm vị trí chèn x
{
m = (l+r)/2;
// tìm vị trí thích hợp m
if(x < a[m]) r = m-1;
else l = m+1;
}
for(int j = i-1 ; j >=l ; j--)
a[j+1] = a[j];// dời các phần tử sẽ đứng sau x
a[l] = x; // chèn x vào dãy }
}

thuật toán insertion sort - chèn trực tiếp

thuật toán insertion sort - chèn trực tiếp

Giả sử có một dãy a0 , a1 ,... ,an-1 trong đó i phần tử đầu tiên a0 , a1 ,... ,ai-1 đã có thứ tự.
Tìm cách chèn phần tử  ai vào vị trí thích hợp của đoạn đã được sắp để có dãy mới a0 , a1,... ,ai trở nên có thứ tự. Vị trí này chính là vị trí giữa hai phần tử ak-1 và ak thỏa ak-1 < ai < ak (1≤k≤i).

Bước 1:  i = 1; //giả sử có đoạn a[1] đã được sắp
Bước 2: x = a[i]; Tìm vị trí pos thích hợp trong đoạn a[1] đến a[i-1] để chèn a[i] vào
Bước 3: Dời chỗ các phần tử  từ a[pos] đến a[i-1]   sang phải 1 vị trí để dành chổ cho a[i]
Bước 4: a[pos] = x; //có đoạn a[1]..a[i]  đã được sắp
Bước 5: i = i+1;
Nếu  i < n : Lặp lại Bước 2
Ngược lại  : Dừng

void InsertionSort(int d, int n 
{ int pos, i;
int x;//lưu giá trị a[i] tránh bị ghi đè khi dời chỗ các phần tử.
for(i=1 ; i<n ; i++) //đoạn a[0] đã sắp
{
x = a[i]; pos = i-1;
// tìm vị trí chèn x
while((pos >= 0)&&(a[pos] > x))
{//kết hợp dời chỗ các phần tử sẽ đứng sau x trong dãy mới
a[pos+1] = a[pos];
pos--;
}
a[pos+1] = x; // chèn x vào dãy
}
}

Tuesday, March 17, 2015

sắp xếp từ điển trong lập trình C++ - bài tập đồ án CTDL & GT

sắp xếp từ điển trong lạp trình C++ - bài tập đồ án CTDL & GT

sắp xếp từ điển trong lập trình c/c++,tạo 1 mảng 1 chiều chứa các từ tiếng anh lấy từ file http://blackberryvietnam.net/threads/du-lieu-tu-dien-cho-ung-dung-ddict.897/ . sau đó dùng các thuật toán sắp xếp để sắp xếp mảng trên theo thứ tự và so sánh thời gian thực hiện các thuật toán.
lưu ý:để thuận tiện việc thao tác, chỉ lấy các từ đơn dưới 15 kí tự, các từ tiếng anh được tách ra từ dữ liệu từ điển việt-anh. (không phải từ điển anh-việt).
trong code dưới đây, dữ liệu nguồn là file va.dd, danh sách các từ tiếng anh lọc ra được và sắp xếp được đưa vào file av.dd.
*đây là bài tập đồ án của thầy Toàn UIT, dưới đây chỉ là các code sắp xếp, phần main() thì các bạn chỉnh sửa lại cho phù hợp với yêu cầu của đồ án, phần main() là ý kiến sáng tạo để hoàn thành bài tập, tôi chỉ viết đơn giản như vậy để chạy thử xem code sắp xếp có chạy đúng hay không thôi.



#include<iostream>
#include<time.h>
using namespace std;

void bang(char *a,char *b);
void doi(char *a,char *b);

//các thuật toán sắp xếp
void interchange(char s[][15],int k);
void select(char s[][15],int n);
void bubble(char s[][15],int n);
void insert(char s[][15],int n);
void insertbinary(char s3[][15],int k);
void shacker(char s[][15],int n);
void shell(char s[][15],int n);
void quick(char s[][15],int l,int r);
void heap(char s[][15],int n);
void merge(char a[][15],int n);

void main()
{
//lấy các từ tiếng anh đưa vào chuỗi s3
FILE *t,*t1;
char s[300];
char *s1,*s2,s3[50000][15];
t = fopen("E:\\va.dd","r");
t1=fopen("E:\\av.dd","w+");
while(fgets(s,300,t)!=NULL)
{
s1=strstr(s,"##");
if(s1!=NULL)
{
s2=strstr(s1,"|-");
if(s2!=NULL && strlen(s2)<15) fputs(s2+2,t1);
}
}
rewind(t1);
int k=0;
while(fgets(s,15,t1)!=NULL)
{
strcpy(s3[k],s);
k++;
}
int n=k;  
//sắp xếp
cout<<"\ndang sap xep...";
double tg;
double a=clock();
shell(s3,k);//kiểu sắp xếp. thay bằng các kiểu sắp xếp khác nhau để so sanh thời gian
//đang dùng shell sort..
double b=clock();
cout<<"\nda xep xong!\nthoi gian sap xep la: "<<(b-a)/1000<<" giay.";

rewind(t1);
for(int i=0;i<k;i++) fputs(s3[i],t1);
fcloseall();
system("pause"); 
}
void chinh(char s[][15],int l,int r)
{
int j=2*l+1;
while(j<=r)
{
if(j<r && stricmp(s[j],s[j+1])<0) j++;
if(stricmp(s[l],s[j])>=0) return;
else
{
doi(s[l],s[j]);
l=j;
j=2*l+1;
}
}
}
void taoheap(char s[][15],int n)
{
int l=n/2-1;
while(l>=0)
{
chinh(s,l,n-1);
l--;
}
}
void heap(char s[][15],int n)
{
int r=n-1;
taoheap(s,n);
while(r>0)
{
doi(s[0],s[r]);
r--;
if(r>0) chinh(s,0,r);
}
}
void quick(char s[][15],int l,int r)
{
int i=l,j=r,m=(l+r)/2;
while(i<=j)
{
while(stricmp(s[i],s[m])<0) i++;
while(stricmp(s[j],s[m])>0) j--;
if(i<=j)
{
doi(s[i],s[j]);
i++;j--;
}
}
if(i<r) quick(s,i,r);
if(j>l) quick(s,l,j);
}
void shacker(char s[][15],int n)
{
int l=0,r=n-1,k=n-1,i;
while(l<r)
{
for(i=r;i>l;i--)
if(stricmp(s[i],s[i-1])<0){ doi(s[i],s[i-1]);k=i;}
l=k;
for(i=l;i<r;i++)
if(stricmp(s[i],s[i+1])>0){doi(s[i],s[i+1]);k=i;}
r=k;
}
}
void bubble(char s[][15],int n)
{
for(int i=0;i<n-1;i++)
for(int j=n-1;j>i;j--)
if(stricmp(s[j],s[j-1])<0) doi(s[j],s[j-1]);
}
void insert(char s[][15],int n)
{
for(int i=1;i<n;i++)
{
char x[15];
bang(x,s[i]);
int j=i-1;
while(stricmp(s[j],x)>0 && j>=0)
{
bang(s[j+1],s[j]);
j--;
}
bang(s[j+1],x);
}
}
void interchange(char s[][15],int k)
{
for(int i=0;i<k-1;i++)
for(int j=i+1;j<k;j++)
if(stricmp(s[i],s[j])>0) doi(s[i],s[j]);
}
void select(char s[][15],int n)
{
int dem=0;
for(int i=0;i<n-1;i++)
{
int m=i;
for(int j=i+1;j<n;j++)
if(stricmp(s[m],s[j])>0) m=j;
doi(s[i],s[m]);
}
}
void shell(char s[][15],int n)
{
int h[10]={10129,1678,437,256,134,62,5,3,2,1},k=10;
int i,j,len,step;
char x[15];
for(step=0;step<k;step++)
{
len=h[step];
for(i=len;i<n;i++)
{
bang(x,s[i]);
j=i-len;
while(j>=0 && stricmp(s[j],x)>0)
{
bang(s[j+len],s[j]);
j=j-len;
}
bang(s[j+len],x);
}
}
}
void insertbinary(char s3[][15],int k)
{
//sắp xếp chèn nhị phân
int l,r,m,i,j,dem=0;
char x[15];
for(i=1;i<k;i++)
{
l=0;r=i-1;
for(j=0;j<strlen(s3[i]);j++) x[j]=s3[i][j];x[j]='\0';
while(l<=r)
{
m=(l+r)/2;
if(stricmp(x,s3[m])<0) r=m-1;
else l=m+1;
}
for(j=i;j>l;j--) bang(s3[j],s3[j-1]);
bang(s3[l],x);
}
}
void bang(char *a,char *b)//phép gán
{
int i;
for(i=0;i<strlen(b);i++) a[i]=b[i];
a[i]='\0';
}
void doi(char *a,char *b)//hoán đổi vị trí
{
int i;
char c[300];
for(i=0;i<strlen(a);i++) c[i]=a[i];c[i]='\0';
for(i=0;i<strlen(b);i++) a[i]=b[i];a[i]='\0';
for(i=0;i<strlen(c);i++) b[i]=c[i];b[i]='\0';

}
void phanphoi(char a[][15],int n,char b[][15],int &nb,char c[][15],int &nc,int k)
{
int pa,pb,pc,i;
pa=pb=pc=0;
while(pa<n)
{
i=0;
while(i<k && pa<n)
{
bang(b[pb++],a[pa++]);
i++;
}
i=0;
while(i<k && pa<n)
{
bang(c[pc++],a[pa++]);
i++;
}
}
nb=pb;nc=pc;
}
int min(int a,int b)
{
if(a<b) return a;
return b;
}
void tron(char a[][15],int n,char b[][15],int nb,char c[][15],int nc,int k)
{
int pa,pb,pc,kb,kc,ib,ic;
pa=pb=pc=ib=ic=0;
while(nb>0 && nc>0)
{
kb=min(k,nb);
kc=min(k,nc);
if(stricmp(b[pb+ib],c[pc+ic])<=0)
{
bang(a[pa++],b[pb+ib]);
ib++;
if(ib==kb)
{
while(ic<kc)
{
bang(a[pa++],c[pc+ic]);
ic++;
}
pb+=kb;pc+=kc;nb-=kb;nc-=kc;
ib=ic=0;
}
}
else
{
bang(a[pa++],c[pc+ic]);
ic++;
if(ic==kc)
{
while(ib<kb)
{
bang(a[pa++],b[pb+ib]);
ib++;
}
pb+=kb;pc+=kc;nb-=kb;nc-=kc;
ib=ic=0;
}
}
}
}
void merge(char a[][15],int n)
{
char (*b)[15]=new char[50000][15];
char (*c)[15]=new char[50000][15];
int nb,nc,k=1;
while(k<n)
{
phanphoi(a,n,b,nb,c,nc,k);
tron(a,n,b,nb,c,nc,k);
k*=2;
}
delete [](*b);
delete [](*c);

}


file sắp xếp từ điển

//tác giả code: Trần Khánh Toàn - ĐH CNTT