Professional Documents
Culture Documents
Chuong4 2
Chuong4 2
28 3.1415 'A'
Primitive Data Types
array
Basic Data Structures
insert(3, ‘z’)
0 1 2 3 4 5 6 7 8 9
z
a b c d e f g h
count=9
count=8
1.1.a. Thêm một phần tử vào một
danh sách kế tiếp
Algorithm Insert
Input: index là vị trí cần thêm vào, element là giá trị cần thêm vào
Output: tình trạng danh sách
if list đầy
return overflow
if index nằm ngoài khoảng [0..count]
return range_error
//Dời tất cả các phần tử từ index về sau 1 vị trí
for i = count-1 down to index
entry[i+1] = entry[i]
entry[index] = element // Gán element vào vị trí index
count++ // Tăng số phần tử lên 1
return success;
End Insert
1.1.b.Xóa 1 phần tử khỏi danh sách
kế tiếp
remove(3, ‘d’)
0 1 2 3 4 5 6 7 8 9
a b c d e f g h
count=7
count=8
1.1.b.Xóa 1 phần tử khỏi danh sách
kế tiếp
Algorithm Remove
Input: index là vị trí cần xóa bỏ, element là giá trị lấy ra được
Output: danh sách đã xóa bỏ phần tử tại index
if list rỗng
return underflow
if index nằm ngoài khoảng [0..count-1]
return range_error
element = entry[index] //Lấy element tại vị trí index ra
count-- //Giảm số phần tử đi 1
//Dời tất cả các phần tử từ index về trước 1 vị trí
for i = index to count-1
entry[i] = entry[i+1]
return success;
End Remove
.1.c.Duyệt danh sách kế tiếp
Algorithm Traverse
Input: hàm visit dùng để tác động vào từng phần tử
Output: danh sách được cập nhật bằng hàm visit
End Traverse
1.2. Danh sách nối đơn
• Một phần tử trong INFO N
danh sách = một L E
X
nút T
• Head = NULL
Node *newNode;
newNode=
malloc(sizeof(Node));
newNode->data = 20;
newNode->next = NULL;
Head = newNode;
Thêm một nút vào đầu danh sách
newNode= malloc(sizeof(Node));
newNode->data = 13;
newNode->next = Head;
Head = newNode;
Thêm một nút vào giữa/cuối danh
sách
newNode= malloc(sizeof(Node));
newNode->data = 13;
newNode->next = currNode->next;
currNode->next= newNode;
Thêm một nút mới
Node *InsertNode(Node *head, int index, int x)
• Thêm một nút mới với dữ liệu là x vào sau nút thứ index.
(vídụ,khi index = 0, nút được thêm là phần tử đầu danh sách;khi index = 1, chèn
nút mới vào sau nút đầu tiên,v.v)
• Nếu thao tác thêm thành công,trả lại nút được thêm.
Ngược lại,trảlạiNULL.
• (Nếu index < 0 hoặc > độ dài của danh sách,không thêm được.)
Giải thuật
1.Tìm nút thứ index –currNode
2.Tạo nút mới
3.Móc nối nút mới vào danh sách
newNode->next = currNode->next;
currNode->next = newNode;
Thêm một nút mới
Node * InsertNode(Node *head,int index,int x)
{
if (index < 0) return NULL;
int currIndex = 1; Tìm nút thứ index, nếu
Node *currNode = head; Không tìm được trả về
while(currNode && index > currIndex) { NULL
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode== NULL) return NULL;
Tạo nút mới
Node *newNode = (Node *) malloc(sizeof(Node));
newNode->data = x;
if (index == 0) {
newNode->next = head; Thêm vào đầu ds
head = newNode;}
else {
newNode->next = currNode->next; Thêm vào sau currNode
currNode->next = newNode;}
return newNode;
}
Tìm nút
int FindNode(intx)
• Tìm nút có giá trị x trong danh sách.
• Nếu tìm được trả lại vị trí của nút.Nếu không, trả lại 0.
Int FindNode(Node *head,int x) {
Node *currNode = head;
int currIndex = 1;
while (currNode && currNode->data != x) {
currNode = currNode->next;
currIndex++;
}
if (currNode) return currIndex;
else return 0;
}
Xóa nút
int DeleteNode(int x)
• Xóa nút có giá trị bằng x trong danh sách.
• Nếu tìm thấy nút, trả lại vị trícủa nó.
Nếu không, trả lại 0.
• Giải thuật
– Tìm nút có giá trị x (tương tự như FindNode)
– Thiết lập nút trước của nút cần xóa nối đến nút sau
của nút cần xóa
– Giải phóng bộ nhớ cấp phát cho nút cần xóa
– Giống như InsertNode, có 2 trường hợp
• Nút cần xóa là nút đầu tiên của danh sách
• Nút cần xóa nằm ở giữa hoặc cuối danh sách
Int DeleteNode(Node *head, int x) {
Node *prevNode = NULL;
Node *currNode = head;
int currIndex = 1;
while (currNode && currNode->data != x) {
prevNode = currNode;
currNode = currNode->next; Tìm nút có giá trị = x
currIndex++;
}
if (currNode) { Xóa nút ở giữa
if (prevNode) {
prevNode->next = currNode->next;
free (currNode);
} else {
head = currNode->next; Xóa nút head
free (currNode);
}
return currIndex;
}
return 0;
}
Hủy danh sách
void DestroyList(Node *head)
• Dùng để giải phóng bộ nhớ được cấp phát cho danh sách.
• Duyệt toàn bộ danh sách và xóa lần lượt từng nút.
• Xóa nút Cur(không phải nút đầu hoặc cuối danh sách)
(Cur->prev)->next = Cur->next;
(Cur->next)->prev = Cur->prev;
free (Cur);
Danh sách nối kép với nút đầu giả
• Danh sách không
rỗng
– Lưu trữ móc nối: sử dụng danh sách móc nối (sau)
Cấu trúc dữ liệu
/* Stack của các số nguyên: intstack*/
typedef struct intstack{
Int *stackArr; /*mảng lưu trữ các phần tử*/
Int count; /*số ptử hiện có của stack */
Int stackMax; /* giới hạn Max của số ptử*/
Int top; /*chỉ số của phần tử đỉnh*/
} IntStack;
Tạo Stack
IntStack *CreateStack(int max){
IntStack *stack;
stack =(IntStack *) malloc(sizeof(IntStack));
if (stack == NULL)
return NULL;
/*Khởi tạo stack rỗng*/
stack->top = -1;
stack->count = 0;
stack->stackMax= max;
stack->stackArr=malloc(max * sizeof(int));
return stack ;
}
Push
Int PushStack(IntStack *stack, int dataIn) {
/*Kiểm tra tràn*/
if(stack->count == stack->stackMax)
Return 0;
/* Thêm phần tử vào stack */
(stack->count)++;
(stack->top)++; /* Tăng đỉnh */
stack->stackArr[stack->top] =dataIn;
Return 1;
}
Pop
Int PopStack(IntStack *stack, int *dataOut){
/* Kiểm tra stack rỗng */
if(stack->count == 0)
return 0;
/* Lấy giá trị phần tử bị loại*/
*dataOut=stack->stackArr[stack->top];
(stack->count)--;
(stack->top)--; /* Giảm đỉnh */
Return 1;
}
Top
Int TopStack(IntStack *stack, int *dataOut){
if(stack->count ==0) // Stack rỗng
return 0;
*dataOut = stack->stackArr[stack->top];
return 1;
}
Kiểm tra rỗng ?
Int IsEmptyStack(IntStack *stack){
return(stack->count == 0);
}
Kiểm tra đầy ?
intIsFullStack(IntStack*stack) {
return(stack->count==stack->stackMax);
}
Ứng dụng của Stack
Bài toán đổi cơ số:Chuyển một số từ hệ
thập phân sang hệ cơ số bất kỳ
• (base 8) 2810 = 3•81+ 4•80=348
• (base 4) 7210 = 1•43+ 0•42+ 2•41+ 0•40=
10204
• (base 2) 5310 = 1 •25+ 1 •24+ 0 •23+ 1 •22+
0 •21+ 1 •20= 1101012
Đầu vào số thập phân n, cơ số b
Đầu ra số hệ cơ số b tương đương
1.Chữ số bên phải nhất của kết quả=n % b. Đẩy vào Stack.
2.Thay n= n / b (để tìm các số tiếp theo).
3.Lặp lại bước1-2 cho đến khi n = 0.
4.Rút lần lượt các chữ số lưu trong Stack, chuyển sang dạng
ký tự tương ứng với hệ cơ số trước khi in ra kết quả
Ví dụ : Đổi 3553 sang cơ số 8
Chuyển sang dạng ký tự tương ứng:
3
+
-8 -8
2
*
-4 -4
11
-
7 7
Tính giá trị của biểu thức hậu tố
typedef structtree_node
{
int data ;
structtree_node *left ;
structtree_node *right ;
}TREE_NODE;
• Tạo cây nhị phân
TREE_NODE *root, *leftChild, *rightChild;
// Tạo nút con trái
leftChild= (TREE_NODE *)malloc(sizeof(TREE_NODE));
leftChild->data = 20;
leftChild->left = leftChild->right = NULL;
// Tạo nút con phải
rightChild = (TREE_NODE *)malloc(sizeof(TREE_NODE));
rightChild->data = 30;
rightChild->left = rightChild->right = NULL;
// Tạo nút gốc
root = (TREE_NODE *)malloc(sizeof(TREE_NODE));
root->data = 10;
root->left = leftChild;
root->right = rightChild;
root -> data= 50;// gán 50 cho root
2.3. Duyệt cây nhị phân
• Duyệt cây: lần lượt duyệt toàn bộ nút trên cây
• Có 3 cách duyệt cây:
– Duyệt theo thứ tự trước
– Duyệt theo thứ tự giữa
– Duyệt theo thứ tự sau
• Định nghĩa duyệt cây nhị phân là những định
nghĩa đệ quy.
Duyệt theo thứ tự trước
1. Thăm nút.
2. Duyệt cây con trái theo thứ tự trước.
3. Duyệt cây con phải theo thứ tự trước.
Duyệt theo thứ tự sau
1. Duyệt cây con trái theo thứ tự sau.
2. Duyệt cây con phải theo thứ tự sau.
3. Thăm nút.
Duyệt theo thứ tự giữa
voidPostorder_iter(TREE_NODE *treeRoot)
{
TREE_NODE *curr= treeRoot;
STACK *stack= createStack(MAX);//ktạo một stack
while( curr != NULL || !IsEmpty(stack)) {
if (curr == NULL) {
while(!IsEmpty(stack) && curr==Top(stack)->right){
PopStack(stack, &curr);
printf(“%d”, curr->data);
}
curr= isEmpty(stack)? NULL: Top(stack)->right;
}
else{
PushStack(stack, curr);
curr= curr->left;
}
}
destroyStack(&stack);// giải phóng stack
}
Một vài ứng dụng của duyệt cây
• Trung tố:( ( 8 -5 ) * ( ( 4 + 2 ) / 3 ) )
• Tiền tố: * -8 5 / + 4 2 3
• Hậu tố: 8 5 -4 2 + 3 / *
(thực chất là các phép duyệt theo tt giữa, trước và sau)
Cài đặt cây biểu thức
• Mỗi nút có 2 con trỏ
struct TreeNode {
InfoNode info ;// Dữ liệu
TreeNode *left ;// Trỏ tới nút con trái
TreeNode *right ; // Trỏ tới nút con phải
};
• InfoNode có 2 dạng
enum OpType { OPERATOR, OPERAND } ;
struct InfoNode {
OpType whichType;
union // ANONYMOUS union
{
char operator;
int operand ;
}
};
int Eval(TreeNode* ptr){
switch(ptr->info.whichType) {
case OPERAND :
returnptr->info.operand ;
case OPERATOR :
switch ( tree->info.operation ){
case ‘+’:
return ( Eval( ptr->left ) + Eval( ptr->right ) ) ;
case ‘-’:
return ( Eval( ptr->left ) -Eval( ptr->right ) ) ;
case ‘*’:
return ( Eval( ptr->left ) * Eval( ptr->right ) ) ;
case ‘/’:
return ( Eval( ptr->left ) / Eval( ptr->right ) ) ;
}
}
}
Cây quyết định
• Dùng để biểu diễn lời giải của bài toán cần
quyết định lựa chọn
• Bài toán 8 đồng tiền vàng:
– Có 8 đồng tiền vàng a, b, c, d, e, f, g, h
– Có một đồng có trọng lượng không chuẩn
– Sử dụng một cân Roberval (2 đĩa)
– Output:
• Đồng tiền k chuẩn là nặng hơn hay nhẹ hơn
• Số phép cân là ít nhất
void EightCoins(a, b, c, d, e, f, g, h) {
if (a+b+c == d+e+f) {
if (g > h) Compare(g, h, a);
else Compare(h, g, a);
}
else if (a+b+c > d+e+f){
if (a+d == b+e) Compare(c, f, a);
else if (a+d > b+e) Compare(a, e, b);
else Compare(b, d, a);
}
else{
if (a+d == b+e) Compare(f,c,a);
else if (a+d > b+e) Compare(d, b, a);
else Compare(e, a, b);
}
}
// so sánh x với đồng tiền chuẩn z
void Compare(x,y,z){
if(x>y) printf(“x nặng”);
else printf(“y nhẹ”);
}
Cac giai thuat tim kiem va sap xep
• SV tu nghien cuu !!!