编程C本: 帖子 14 – 双向链表


双链表是一个链表的格式,但与元件前面并在列表如下它的每个元素相关联的

双向链表
双向链表

1 安装列表

的结构 1 节点的双向链表类似的列表,以DSLKD,但更多的是指向前节点

typedef int item;

typedef struct Node //cau truc 1 Node
{
	item Data; //du lieu cua Node
	Node *Left; //Con tro trai
	Node *Right; //con tro phai
};

typedef struct DList //cau truc Cua List
{
	Node *Head; //con tro dau
	Node *Tail; //con tro cuoi
};

这样DSLKD DSLKK的结构没有 1 指向第一个DS, 但是DSLKK外指针列表仍进一步 1 节点指针列表的末尾

2 初始化和检查空

它被初始化为 2 开始和结束指针返回NULL, 当测试执行只看到一个空的头指针NULL指针是不够的

void Init(DList &L) 
{
	L.Head = NULL; // Con tro dau tro den NULL
	L.Tail = NULL; // Con tro cuoi tro den NULL
}

int Isempty (DList L) //kiem tra DS rong
{
    return (L.Head == NULL);
}

3. 列表的长度

找到DSLKK的长度,我们绝对可以做到像DSLKD, 从开始的即时审批指针完成, 但我们可以用DSLKK 2 光标在开始和计数结束

int Len (DList L) // Do dai danh sach
{
    Node *PH = L.Head, *PT = L.Tail; //tao Node PH (con tro duyet tu dau DS) và PT (con tro duyet tu cuoi DS) de duyet danh sach L
    int i = 0; //bien dem
    if (PH != NULL) i = 1;
    while (PH != NULL) //trong khi P chua tro den NULL (cuoi danh sach thi lam)
    {
        if (PH == PT) break;
        PH = PH->Right; //cho PH tro den Node tiep theo
        i++;
        if (PH == PT) break;
        PT = PT->Left; //cho PT tro den Node truoc do
        i++;
    }
    return i; //tra lai so Node cua L
}

4. 创建 1 节点P包含的信息

Node *Make_Node (item x) //tao 1 Node P chua thong tin la x 
{
	Node *P = (Node *) malloc (sizeof (Node)); //Cap phat vung nho cho P
    P->Data = x; //Ghi du lieu vao Data
    P->Left = NULL; 
    P->Right = NULL; 
    return P; 
}

5. 插入元件到第一位置

插入列表的顶部之前,以检查是否该列表为空或不. 如果我们空单的头和尾都指向P. 如果没有执行插入空.

void Insert_first (DList &L, item x)  //Chen x vao vi tri dau tien trong danh sach
{
    Node *P;
    P = Make_Node(x); //tao 1 Node P
    if (Isempty(L)) //Neu danh sach rong
    {
		L.Head = P;
		L.Tail = P;
	}
	else
	{
		P->Right = L.Head; 
		L.Head->Left = P;
		L.Head = P;
	}
}

6. 插入所述列表中的元素的末尾类似于列表

void Insert_last (DList &L, item x)  //Chen x vao vi tri cuoi trong danh sach
{
    Node *P;
    P = Make_Node(x); //tao 1 Node P
    if (Isempty(L)) //Neu danh sach rong
    {
		L.Head = P;
		L.Tail = P;
	}
	else
	{
		L.Tail->Right = P; //ket noi voi danh sach
		P->Left = L.Tail; //P tro ve Node truoc
		L.Tail = P; //luu lai vi tri cuoi
	}
}

7. 插入元素到位置k

在地方插入前检查位置kķ匹配, 是所述列表或多个列表的末尾. 如果列表我跟随之间插入 4 步骤

将X的位置k在双向链表
将X的位置k在双向链表
void Insert_k (DList &L, item x, int k) //chen x vao vi tri k trong danh sach
{
    Node *PH = L.Head, *PT, *R;
    int i=1, l = Len(L);
    if (k<1 || k> l+1) printf("Vi tri chen khong hop le !"); //kiem tra dieu kien
    else
    {
        R = Make_Node(x); //tao 1 Node P
        if (k == 1) Insert_first(L,x); //chen vao vi tri dau tien
        else
			if (k == l+1) Insert_last(L,x); //chen vao vi tri cuoi
			else //chen vao vi tri 1<k<l+1
			{
				while (PH != NULL && i != k-1) //duyet den vi tri k-1
				{
					i++;
					PH = PH->Right;
				}
				PT = PH->Right; //xac dinh vi tri k
				R->Right = PT; 	//(1)
				R->Left = PH;	//(2)
				PH->Right = R;	//(3)
				PT->Left = R;	//(4)
			}
    }
}

8. 除去第一元件, 列表的末尾

// Lay gia tri can xoa ra, sau do bo qua 1 Node dau tien
void Del_first (DList &L, item &x) //Xoa phan tu dau tien
{
	if (!Isempty(L))
	{
		x = L.Head->Data; //lay gia tri ra neu can dung
		L.Head = L.Head->Right; //Cho L tro den Node thu 2 trong danh sach
	}
}

// Lay gia tri can xoa ra, sau do bo qua 1 Node cuoi
void Del_last (DList &L, item &x) //Xoa phan tu dau tien
{
	if (!Isempty(L))
	{
		x = L.Tail->Data;
		L.Tail = L.Tail->Left;
		L.Tail->Right = NULL;
	}
}

9. 在位置k删除元素

删除到位前检查位置kķ匹配, 是所述列表或多个列表,或结束时在中间

void Del_k (DList &L, item &x, int k) //Xoa Node k trong danh sach
{
    Node *PH = L.Head, *PT;
    int i=1, l = Len(L);
    if (k<1 || k> l) printf("Vi tri xoa khong hop le !"); //kiem tra dieu kien
    else
    {
        if (k == 1) Del_first(L,x); //xoa vi tri dau tien
        else
			if (k == l) Del_last(L,x); //xoa vi tri cuoi
			else //xoa vi tri 1<k<l+1
			{
				while (PH != NULL && i != k-1) //duyet den vi tri k-1
				{
					i++;
					PH = PH->Right;
				}
				x = PH->Right->Data;
				PT = PH->Right->Right; //xac dinh vi tri k+1
				PH->Right = PT; 	
				PT->Left = PH;	
			}
    }
}

10. 查找元素x在DS

int Search (DList L, item x) //tim x trong danh sach
{
    Node *P=L.Head; 
    int i=1;
    while (P != NULL && P->Data != x) //duyet danh sach den khi tim thay hoac ket thuc danh sach
    {
        P = P->Right;
        i++;
    }
    if (P != NULL) return i; //tra ve vi tri tim thay
    else return 0; //khong tim thay
}

11. 在DS删除元素x

void Del_x (DList &L, item x) //xoa phan tu x trong danh sach
{
	int l = Search(L,x);
    while (l)
    {
		Del_k (L,x,l); //trong khi van tim thay x thi van xoa
		l = Search(L,x);
	}
}

12. 完整的程序

#include <stdlib.h>
#include <stdio.h>
typedef int item;

typedef struct Node //cau truc 1 Node
{
	item Data; //du lieu cua Node
	Node *Left; //Con tro trai
	Node *Right; //con tro phai
};

typedef struct DList //cau truc Cua List
{
	Node *Head; //con tro dau
	Node *Tail; //con tro cuoi
};

void Init(DList &L);
int Isempty (DList L); //kiem tra DS rong
int Len (DList L); // Do dai danh sach
Node *Make_Node (Node *P, item x); //tao 1 Node P chua thong tin la x 
void Insert_first (DList &L, item x);  //Chen x vao vi tri dau tien trong danh sach
void Insert_last (DList &L, item x);  //Chen x vao vi tri dau tien trong danh sach
void Insert_k (DList &L, item x, int k); //chen x vao vi tri k trong danh sach
void Del_first (DList &L, item &x); //Xoa phan tu dau tien
void Del_k (DList &L, item &x, int k); //Xoa Node k trong danh sach
int Search (DList L, item x); //tim x trong danh sach
void Del_x (DList &L, item x); //xoa phan tu x trong danh sach
void Input (DList &L); //nhap danh sach
void Output (DList L); //xuat danh sach


void Init(DList &L) 
{
	L.Head = NULL; // Con tro dau tro den NULL
	L.Tail = NULL; // Con tro cuoi tro den NULL
}

int Isempty (DList L) //kiem tra DS rong
{
    return (L.Head == NULL);
}

int Len (DList L) // Do dai danh sach
{
    Node *PH = L.Head, *PT = L.Tail; //tao Node PH (con tro duyet tu dau DS) và PT (con tro duyet tu cuoi DS) de duyet danh sach L
    int i = 0; //bien dem
    if (PH != NULL) i = 1;
    while (PH != NULL) //trong khi P chua tro den NULL (cuoi danh sach thi lam)
    {
        if (PH == PT) break;
        PH = PH->Right; //cho PH tro den Node tiep theo
        i++;
        if (PH == PT) break;
        PT = PT->Left; //cho PT tro den Node truoc do
        i++;
    }
    return i; //tra lai so Node cua L
}

Node *Make_Node (item x) //tao 1 Node P chua thong tin la x 
{
	Node *P = (Node *) malloc (sizeof (Node)); //Cap phat vung nho cho P
    P->Data = x; //Ghi du lieu vao Data
    P->Left = NULL; 
    P->Right = NULL; 
    return P; 
}

void Insert_first (DList &L, item x)  //Chen x vao vi tri dau tien trong danh sach
{
    Node *P;
    P = Make_Node(x); //tao 1 Node P
    if (Isempty(L)) //Neu danh sach rong
    {
		L.Head = P;
		L.Tail = P;
	}
	else
	{
		P->Right = L.Head; 
		L.Head->Left = P;
		L.Head = P;
	}
}
//Chen vao cuoi danh sach cung tuong tu

void Insert_last (DList &L, item x)  //Chen x vao vi tri cuoi trong danh sach
{
    Node *P;
    P = Make_Node(x); //tao 1 Node P
    if (Isempty(L)) //Neu danh sach rong
    {
		L.Head = P;
		L.Tail = P;
	}
	else
	{
		L.Tail->Right = P; //ket noi voi danh sach
		P->Left = L.Tail; //P tro ve Node truoc
		L.Tail = P; //luu lai vi tri cuoi
	}
}

void Insert_k (DList &L, item x, int k) //chen x vao vi tri k trong danh sach
{
    Node *PH = L.Head, *PT, *R;
    int i=1, l = Len(L);
    if (k<1 || k> l+1) printf("Vi tri chen khong hop le !"); //kiem tra dieu kien
    else
    {
        R = Make_Node(x); //tao 1 Node P
        if (k == 1) Insert_first(L,x); //chen vao vi tri dau tien
        else
			if (k == l+1) Insert_last(L,x); //chen vao vi tri cuoi
			else //chen vao vi tri 1<k<l+1
			{
				while (PH != NULL && i != k-1) //duyet den vi tri k-1
				{
					i++;
					PH = PH->Right;
				}
				PT = PH->Right; //xac dinh vi tri k
				R->Right = PT; 	//(1)
				R->Left = PH;	//(2)
				PH->Right = R;	//(3)
				PT->Left = R;	//(4)
			}
    }
}

void Del_first (DList &L, item &x) //Xoa phan tu dau tien
{
	if (!Isempty(L))
	{
		x = L.Head->Data; //lay gia tri ra neu can dung
		L.Head = L.Head->Right; //Cho L tro den Node thu 2 trong danh sach
	}
}

void Del_last (DList &L, item &x) //Xoa phan tu dau tien
{
	if (!Isempty(L))
	{
		x = L.Tail->Data;
		L.Tail = L.Tail->Left;
		L.Tail->Right = NULL;
	}
}

void Del_k (DList &L, item &x, int k) //Xoa Node k trong danh sach
{
    Node *PH = L.Head, *PT;
    int i=1, l = Len(L);
    if (k<1 || k> l) printf("Vi tri xoa khong hop le !"); //kiem tra dieu kien
    else
    {
        if (k == 1) Del_first(L,x); //xoa vi tri dau tien
        else
			if (k == l) Del_last(L,x); //xoa vi tri cuoi
			else //xoa vi tri 1<k<l+1
			{
				while (PH != NULL && i != k-1) //duyet den vi tri k-1
				{
					i++;
					PH = PH->Right;
				}
				x = PH->Right->Data;
				PT = PH->Right->Right; //xac dinh vi tri k+1
				PH->Right = PT; 	
				PT->Left = PH;	
			}
    }
}

int Search (DList L, item x) //tim x trong danh sach
{
    Node *P=L.Head; 
    int i=1;
    while (P != NULL && P->Data != x) //duyet danh sach den khi tim thay hoac ket thuc danh sach
    {
        P = P->Right;
        i++;
    }
    if (P != NULL) return i; //tra ve vi tri tim thay
    else return 0; //khong tim thay
}

void Del_x (DList &L, item x) //xoa phan tu x trong danh sach
{
	int l = Search(L,x);
    while (l)
    {
		Del_k (L,x,l); //trong khi van tim thay x thi van xoa
		l = Search(L,x);
	}
}


void Input (DList &L) //nhap danh sach
{
    int i=0; 
    item x;
    do
    {
        i++;
        printf ("Nhap phan tu thu %d : ",i);
        scanf("%d",&x);
        if (x != 0) Insert_k(L,x,Len(L)+1);
    } while(x != 0); //nhap 0 de ket thuc
}

void Output (DList L) //xuat danh sach
{
    Node *P=L.Head;
    while (P != L.Tail->Right)
    {
        printf("%5d",P->Data);
        P = P->Right;
    }
    printf("\n");
}

int main()
{
    DList L;
    Init(L);
    Input(L);
    Output(L);

    int lua_chon;
    printf("Moi ban chon phep toan voi DS LKD:");
    printf("\n1: Kiem tra DS rong");
    printf("\n2: Do dai DS");
    printf("\n3: Chen phan tu x vao vi tri k trong DS");
    printf("\n4: Tim mot phan tu trong DS");
    printf("\n5: Xoa phan tu tai vi tri k");
    printf("\n6: XOa phan tu x trong DS");
    printf("\n7: Thoat");
    do
    {
        printf("\nBan chon: ");
        scanf("%d",&lua_chon);
		switch (lua_chon)
		{
			case 1:
			{
				if (Isempty(L)) printf("DS rong !");
				else printf ("DS khong rong !");
				break;
			}
			case 2: printf ("Do dai DS la: %d.",Len(L));break;
			case 3:
			{
				item x;
				int k;
				printf ("Nhap phan tu can chen vao DS: ");
				scanf("%d",&x);
				printf ("Nhap vi tri can chen: ");
				scanf ("%d",&k);
				Insert_k (L,x,k);
				printf ("DS sau khi chen:\n");
				Output(L);
				break;
			}
			case 4:
			{
				item x;
				printf ("Moi ban nhap vao phan tu can tim: ");
				scanf("%d",&x);
				int k=Search(L,x);
				if (k) printf ("Tim thay %d trong DS tai vi tri thu: %d",x,k);
				else printf ("Khong tim thay %d trong danh sach !",x);
				break;
			}
			case 5:
			{
				int k;
				item x;
				printf ("Nhap vi tri can xoa: ");
				scanf ("%d",&k);
				Del_k (L,x,k);
				printf ("DS sau khi xoa:\n");
				Output(L);
				break;
			}
			case 6:
			{
				item x;
				printf ("Nhap phan tu can xoa: ");
				scanf ("%d",&x);
				Del_x (L,x);
				printf ("DS sau khi xoa:\n");
				Output(L);
				break;
			}
			case 7: break;
		}
	}while (lua_chon !=7);
	return 0;
}

[RPS-包括交=”2703″ 简码=”假”]