第十二章 使用结构和指针

这一章主要就是实现了一个链表:

第一段程序

int
sll_insert( Node *current, int new_value )
{
	Node	*previous;
	Node	*new;
	while( current->value < new_value ){/**/
		previous = current;
		current = current->link;
	}
	new = (Node *)malloc( sizeof( Node ) );
	if( new == NULL )
		return FALSE;
	new->value = new_value;

	new->link = current;
	previous->link = new;
	return TRUE;
}

错误在于做标记的那一个循环,可能如果一直找到最后没找到,是不是就发生了越界现象。同时,如果我们在第一个结点之前插入一个结点,如何去访问到这个结点,那是很困难的。

所以第二个程序引入了root指针作为形参。

int
sll_insert( Node **rootp, int new_value )
{
	Node	*current;
	Node	*previous;
	Node	*new;

	current = *rootp;
	previous = NULL;

	while( current != NULL && current->value < new_value ){
		previous = current;
		current = current->link;
	}

	new = (Node *)malloc( sizeof( Node ) );
	if( new == NULL )
		return FALSE;
	new->value = new_value;

	new->link = current;
	if( previous == NULL )//判断是不是为第一个结点
		*rootp = new;
	else
		previous->link = new;
	return TRUE;
}
于是想到利用双重链表可以链接的特性,去消除这个previous,只要刚开始让链表指向&root,不管链表有没有改变指向,反正后面连上一个new就对了。

int
sll_insert( register Node **linkp, int new_value )
{
	register Node	*current;
	register Node	*new;

	while( ( current = *linkp ) != NULL &&
	    current->value < new_value )
		linkp = &current->link;//让linkp在不值向root的时候去指向该结点链接下一节点的指针,这时候取*就能建立对下面结点的链接

	new = (Node *)malloc( sizeof( Node ) );
	if( new == NULL )
		return FALSE;
	new->value = new_value;
	new->link = current;
	*linkp = new;
	return TRUE;
}
二重链表:
写的程序和书上不同,比较要注意的地方就是,if语句里面如果有相同的语句可以往前或者往后提出,只要不对它在if里面之后的动作的结果产生影响。

再次简化就考虑if的条件,然后看看哪些值是和这个条件一样的,就可以从语句中提出。

程序如下

#include <stdio.h>
typedef int valuetype;
struct Node;
struct list
{
	Node* head;
	Node* last;
};
struct Node{
	Node* pre;
	Node* next;
	valuetype value;
};

void dll_insert(register list* mylist,valuetype new_value);
fuctionn.cpp

#include "linked_list_node.h"
#include <stdio.h>
#include <stdlib.h>
void dll_insert(register list* mylist,valuetype new_value){
	register Node* current = mylist->head;
	register Node* previous;
	while (current!=NULL && current->value <= new_value)
	{
		if(current->value == new_value)
			return;
		previous = current;
		current = current->next;
	}
	register Node* newnode = (Node*)malloc(sizeof(Node));
	if(newnode == NULL)
	{
		exit(EXIT_FAILURE);
	}
	newnode->value = new_value;
	newnode->next = current;
	if (current != NULL)
	{
		current->pre = newnode;
		if(current == mylist->head)
		{
			mylist->head = newnode;
			newnode->pre = NULL;
		}
		else
		{
			previous->next = newnode;
			newnode->pre = previous;
		}
	}
	else
	{
		if (current == mylist->head)
		{
			newnode->pre = NULL;
			mylist->head = newnode;
		}
		else
		{
			previous->next = newnode;
			newnode->pre = previous;
		}
		mylist->last = newnode;
	}
}
main.cpp

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

int main(){
	register list* mylist = (list*)malloc(sizeof(list));
	if(mylist == NULL)
		return EXIT_FAILURE;
	mylist->last = mylist->head = NULL;
	dll_insert(mylist,1);
	dll_insert(mylist,2);
	dll_insert(mylist,0);
	dll_insert(mylist,4);
	dll_insert(mylist,2);
	return EXIT_SUCCESS;
}
主要就是判断当前链表是不是为空,这个结点要插在链表的头,尾,还是中间。
课后题:

链表的反转:利用3个指针的不断移动,就可以做到反向连接。

Node* sll_reverse(Node* first){
	if(first == NULL)
		return NULL;
	register Node* pre = NULL;
	register Node* cur = first;
	register Node* aft = first->next;
	for (; aft != NULL; )
	{
		cur->next = pre;
		pre = cur;
		cur = aft;
		aft = aft->next;
	}
	cur->next = pre;
	return cur;
}

附上单链表的整个源代码:

linked_node.h

#include <stdio.h>
#include <stdlib.h>
typedef	int valuetype;
struct Node
{
	Node* next;
	valuetype value;
};

bool dll_insert(register Node** root,valuetype newvalue);
Node* sll_reverse(Node* first);
int sll_remove(register Node** rootp,register Node* node);
functionn.cpp

#include "linked_node.h"
#include <stdio.h>
#include <stdlib.h>
bool dll_insert(register Node** root,valuetype newvalue){//当root为空的时候把头结点以及从NULL改变到了newnode
	register Node* current;
	while ((current = *root) != NULL && current->value < newvalue)
	{
		root = ¤t->next;
	}
	register Node* newnode = (Node*)malloc(sizeof(Node));
	if(newnode == NULL)
	{
		exit(EXIT_FAILURE);
		return false;
	}
	newnode->value = newvalue;
	newnode->next = *root;//或者current
	*root = newnode;//即使root没改变是指向头结点的指针的指针,也是成立
	return true;
}

Node* sll_reverse(Node* first){
	if(first == NULL)
		return NULL;
	register Node* pre = NULL;
	register Node* cur = first;
	register Node* aft = first->next;
	for (; aft != NULL; )
	{
		cur->next = pre;
		pre = cur;
		cur = aft;
		aft = aft->next;
	}
	cur->next = pre;
	return cur;
}
int sll_remove(register Node** rootp,register Node* node){
	register Node* current;
	while ((current = *rootp) != NULL && current != node)
	{
		rootp = ¤t->next;
	}
	if(current == NULL)
		return false;
	*rootp = current->next;
	free(node);
	return true;
}


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

int main(){
	register Node* root = (Node*)malloc(sizeof(Node));
	if(root == NULL)
	{
		exit(EXIT_FAILURE);
		return EXIT_FAILURE;
	}
	root = NULL;
	dll_insert(&root,1);
	dll_insert(&root,2);
	dll_insert(&root,3);//为什么不管怎么插入永远指向头结点
	dll_insert(&root,4);
	dll_insert(&root,3);
	root = sll_reverse(root);
	register Node* node = root;
	while (node != NULL && node->value != 2)
	{
		node = node->next;
	}
	if (node != NULL)
		sll_remove(&root,node);
	return EXIT_SUCCESS;
}

这里包括了课后题的删除结点和链表反转

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值