数据结构之线性表(单链表)复习题

通过复习题 对单链表 在进行一下熟悉,巩固。先看看有那些题:

1.设计将单链表L2连接在单链表L1后面的算法;
2.设计无头结点的单链表的删除算法;
3.设计无头结点的单链表的插入算法;
5.设计无头结点的单链表的逆置算法;
6.设计单链表的逆置算法;

在做这些题之前我们需要把单链表创建出来 我们分别创建出 有头结点的单链表和无头结点的单链表,代码如下:

定义单链表结点类型:

/*定义单链表结点*/
typedef struct Node{
	int data;		//数据域 
	struct Node * next;	//指针域 
}Node,*PNode;

创建有头结点的:

//创建带头结点的单链表
PNode Create(int * a,int Length){
	PNode head,p,q;
	head = (PNode)malloc(sizeof(Node));
	head->next = NULL;
	p = head;
	for(int i = 0;i < Length;i++){
		q = (PNode)malloc(sizeof(Node));
		q->data = a[i];
		q->next = NULL;
		p->next = q;
		p = q;
	}
	return head; 
}


创建无头结点的:

//创建不带头结点的单链表
PNode nCreate(int * b,int Length){
	PNode node,p,q;
	if(Length > 0){
		node = (PNode)malloc(sizeof(Node));
		node->data = b[0];
		node->next = NULL;
		p = node;
		for(int i = 1;i < Length;i++){
			q = (PNode)malloc(sizeof(Node));
			q->data = b[i];
			q->next = NULL;
			p->next = q;
			p = q;
		}
		return node;
	}
}

好了链表已经创建完毕让我们 开始做复习题吧

1.设计将单链表L2连接在单链表L1后面的算法;

思路:题意就是将两个链表拼接起来。这就很简单了,在生活当中 如果我们想把两条线 连接成一条线,肯定是将一条线的尾部 和一条线的头部进行连接,这种思路在我们这个题中也是管用的。看代码:

//1.设计将单链表L2连接在单链表L1后面的算法
void ConnectList(PNode L1,PNode L2){
	PNode p;
	p = L1;
	while(p->next != NULL){ //循环找到 L1 的尾部 
		p = p->next;
	}
	p->next = L2->next;     //尾部和头部相连 
}
2.设计无头结点的单链表的删除算法;

思路:删除链表中一个元素,我一开始的思路是寻找到 所删结点的前一个结点,然后再把所删结点的前一个结点的指针域设置成 所删结点的指针域。但是这样会遇到一个困难就是删除第一个无法实现,我这个思路适合有头街点的单链表。后来转化了一下思路 ,把删除元素换一种理解就是:你在单链表中找不到 你删除的那个值,怎么让他找不到呢?简单一些就是让 后面结点的数据域覆盖 所删结点的数据域,把所删结点的指针域设置成后面结点的指针域。就很完美的 完成了删除操作。又有一个问题就是遇到最后一个结点怎么办?我们还需要一个临时变量记录前面的结点,当判断是最后一个结点时,直接删除就可以了。代码如下:

//2.设计无头结点的单链表的删除算法;
bool nDelete(PNode node,int i,int *ptr){
	PNode p,q,m;
	int count = 0;
	p = node;
	while(p!=NULL && count < i-1){ //遍历到第 i 个结点 
		m = p;						//m 是记录 第 i-1 个结点 
		p = p->next;
		count++;
	}
	if(p == NULL){
		return false;
	}else if(p->next == NULL){     //删除最后一个结点时。 
		*ptr = p->data;
		q = p;
		m->next = NULL;
	}else{
		*ptr = p->data;
		q = p->next;
		p->data = q->data;
		p->next = q->next;
	}
	free(q);
	return true;
}
3.设计无头结点的单链表的插入算法;

思路:无头结点的插入算法 麻烦就麻烦在 向第一个位置插入元素了,这里我们采用了和上面删除元素一样的思路,在这里我们可以这样想 :我们向第一个位置插入元素麻烦,我们可不可以向第二个位置插入元素,然后让着两个节点的数据域进行一下交换,是不是也实现在表头插入元素了呢。代码如下:

//3.设计无头结点的单链表的插入算法;
bool nInsert(PNode node,int i,int ndata){
	PNode p = node,q;
	int count =0;
	while(p!=NULL&&count next;
		count++;
	}
	if(p == NULL){
		return false;
	}else{
		q = (PNode)malloc(sizeof(Node));
		q->data = p->data;		//数据域交换 
		q->next = p->next;
		p->data = ndata;		//数据域交换
		p->next = q;
		return true;
	}
}
5.设计无头结点的单链表的逆置算法;

思路:所谓逆置算法就是让调换位置,让第一个和最后一个交换位置,第二个和倒数第二个交换位置 以此类推,但是单链表有个缺点 就是每次都必须从头开始,不像数组 可以通过下标来找到 相应的元素,相对来说寻找第几个元素比较困难费时一些,这里我们可以使用 我们创建 链表时用的 头插法 来实现逆置。就是从头开始遍历,把每个节点提取出来 看做成一个新的结点 ,进行头插 形成一条新链 这就是我们的 逆置链。代码如下:

//5.设计无头结点的单链表的逆置算法
PNode nInverse(PNode node){
	PNode p = NULL,q = NULL,m = NULL;
	p = q = node;
	while(q!=NULL){
		q = q->next;   //记录本节点的下一个结点 
		p->next = m;  //采用头插法 
		m = p;
		p = q;
	//	printf("fsf  ");
	}
	return m;
}
6.设计单链表的逆置算法;

思路:这个和无头结点逆置 基本一样,不在傲述,直接看代码:

//6.设计单链表的逆置算法
void Inverse(PNode head){
	PNode p = NULL,q = NULL, m = NULL;
	p = q = head->next;  //第一个结点 
	while(q!=NULL){
		q = q->next;
		p->next = m;
		m = p;
		p = q;
	}
	head->next = m;
}


好了,这几个复习题基本 讲完,自己在电脑上 练习一下,不理解的地方 拿着笔在纸上写一写,画一画,你就会有思路的。加油

点击源码下载资源









你可能感兴趣的:(数据结构)