数据结构(一)之链表

链表定义比较简单,在此就不介绍了。简单地说明一下设计链表时一些细节,并附上源代码,希望对读者有帮助。链表分为单链表、双链表和循环链表。

在设计链表时建议留出一个标志节点,即表头或哑节点,这样方便删除操作,特别是在设计栈和队列时特别有用。


单链表数据结构和接口定义:

#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;
typedef struct Node *PtrToNode;
typedef PtrToNode List;
typedef PtrToNode Position;

List createList();
void deleteList(List L);
void insertNode(ElementType X, List L, Position P);
void deleteNode(ElementType X, List L);
Position findNode(ElementType X, List L);
Position findPreNode(ElementType X, List L);

struct Node
{
	ElementType Element;
	Position next;
};

/* 创建有表头的单链表 */
List createList()
{
	List L = (List)malloc(sizeof(struct Node)); 
	if(L == NULL)
		return NULL;
	L->next = NULL;

	return L;
}

void deleteList(List L)
{
	Position p;
	Position tmp;

	if(L == NULL)
		return;

	p = L->next;
	free(L);
	while(p != NULL)
	{
		tmp = p;
		p = p->next;
		free(tmp);
	}

	return;
}

void insertNode(ElementType X, List L, Position P)
{
	Position tmp;

	tmp = (Position)malloc(sizeof(struct Node));
	if(tmp == NULL)
		return;

	tmp->Element = X;
	tmp->next = P->next;
	P->next = tmp;

	return;
}


void deleteNode(ElementType X, List L)
{
	Position p;
	Position tmp;

	p = findPreNode(X, L);
	if(p == NULL)
		return;

	tmp = p->next;
	p->next = tmp->next;
	free(tmp);
	return;
}


Position findPreNode(ElementType X, List L)
{
	Position p;

	p = L;
	while(p->next != NULL && p->next->Element != X)
		p = p->next;

	if(p->next == NULL)
		return NULL;

	return p;
}


Position findNode(ElementType X, List L)
{
	Position p;

	p = L->next;
	while(p != NULL && p->Element != X)
		p = p->next;

	return p;
}

简单写了一个测试程序,读者可自行改进:  
void printList(List L)
{
	Position P;

	if(L == NULL || L->next == NULL)
		return;

	P = L->next;
	while(P != NULL)
	{
		printf("%d", P->Element);
		P = P->next;
	}
	printf("\n");

	return;
}

int main()
{
    List L;
	Position P;
	
	L = createList();
	if(L == NULL)
		return 0;
	P = L;
	for(int i=0; i<10; i++)
	{
		insertNode(i, L, P);
	}
	printList(L);

	deleteNode(6, L);
	printList(L);

	insertNode(8, L, P);
	printList(L);

	deleteList(L);
	
	system("pause");

    return 0;
}

双链表在设计时对每个节点添加了一个前继指针,这增加了空间的需求,同时也使得插入和删除的开销增加了一倍。

双链表的具体实现如下:

#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;
typedef struct DNode *PtrToDNode;
typedef PtrToDNode DList;
typedef PtrToDNode Position;

DList createDList();
void deleteDList(DList L);
void insertDNode(ElementType X, DList L, Position P);
void deleteDNode(ElementType X, DList L);
Position findDNode(ElementType X, DList L);

struct DNode
{
	ElementType Element;
	Position pre;
	Position next;
};

/* 创建有表头的单链表 */
DList createDList()
{
	DList L = (DList)malloc(sizeof(struct DNode)); 
	if(L == NULL)
		return NULL;

	L->pre = NULL;
	L->next = NULL;

	return L;
}

void deleteDList(DList L)
{
	Position p;
	Position tmp;

	if(L == NULL)
		return;

	p = L->next;
	free(L);
	while(p != NULL)
	{
		tmp = p;
		p = p->next;
		free(tmp);
	}
}

void insertDNode(ElementType X, DList L, Position P)
{
	Position tmp;

	tmp = (Position)malloc(sizeof(struct DNode));
	if(tmp == NULL)
		return;

	tmp->Element = X;
	tmp->pre = P;
	tmp->next = P->next;
	if(P->next != NULL)
		P->next->pre = tmp;
	P->next = tmp;

	return;
}


void deleteDNode(ElementType X, DList L)
{
	Position p;
	Position pre;
	Position next;

	p = findDNode(X, L);
	if(p == NULL)
		return;

	pre = p->pre;
	next = p->next;

	pre->next = next;
	next->pre = pre;
	free(p);

	return;
}


Position findDNode(ElementType X, DList L)
{
	Position p;

	p = L->next;
	while(p != NULL && p->Element != X)
		p = p->next;

	return p;
}

测试程序:

void printDList(DList L)
{
	Position P;

	P = L->next;
	while(P != NULL)
	{
		printf("%d", P->Element);
		P = P->next;
	}
	printf("\n");

	return;
}


int main()
{
    DList L;
	Position P;
	
	L = createDList();
	if(L == NULL)
		return 0;

	P = L;
	for(int i=0; i<10; i++)
	{
		insertDNode(i, L, P);
	}
	printDList(L);

	deleteDNode(6, L);
	printDList(L);

	insertDNode(6, L, P);
	printDList(L);

	deleteDList(L);

	system("pause");

    return 0;
}

表的应用:
(1)多项式ADT,使用数组或单链表。在项目比较少却次数高时用单链表比较好。
(2)基数排序。也称为卡式排序。基数排序是桶式排序的推广,即多趟桶式排序。
(3)多重表。将两个表合成一个表。所有的表都各有一个表头并且都是循环的。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值