现在的位置: 首页 > 综合 > 正文

链表操作–指针传递 测试与学习

2014年01月02日 ⁄ 综合 ⁄ 共 6004字 ⁄ 字号 评论关闭

链表操作,测试下 通过 指向结点的指针以及 指向结点指针的指针 完成 链表操作。

//链表的实现
#include <stdio.h>
#include <malloc.h>

#define ElemType int
#define LIST_INIT_SIZE 20
#define OK 1
#define ERROR 0

typedef struct Node{
	int data;
	struct Node *next;
}Node, *LinkList;

int CreateList(LinkList *list, int n);
int InsertList(LinkList list, int pos, int n);
int DelList(LinkList *list, int pos, int *n);
int MergeList(LinkList *des_list, LinkList *src_list);//将src_list合并至des_list中,两列表有序 从小到大排列
int ListTraverse(LinkList list); //可传指针,减少复制
int ListLength(LinkList list);
int DestroyList(LinkList *list);//摧毁链表,表头+结点
int ClearList(LinkList *list);//置为空表
int InsertList_p(LinkList *list, int pos, int n); 

int LocatePos(LinkList list, int i, LinkList *des);//用des指向list中第i个结点
int MakeNode(LinkList *node, ElemType e);//
int InsFirst(LinkList *list, LinkList p);
int DelFirst(LinkList list, LinkList p);

#define _POINT_

int main()
{
	LinkList list_q = NULL;
	LinkList list_p = NULL;
	LinkList des = NULL;
	int n, m;

	CreateList(&list_q, 3);
	printf("create list,length:%d \n", ListLength(list_q));
	ListTraverse(list_q);

	MakeNode(&des, 5);
	LocatePos(list_q, 2, &des);

	InsFirst(&list_q, des);
	printf("first insert,length:%d \n", ListLength(list_q));
	ListTraverse(list_q);

	DelFirst(list_q, des);
	printf("first del,length:%d \n", ListLength(list_q));
	ListTraverse(list_q);

	CreateList(&list_p, 3);
	printf("create list,length:%d \n", ListLength(list_q));
	ListTraverse(list_p);


	MergeList(&list_p, &list_q);
	printf("after merge,length:%d \n", ListLength(list_p));
	ListTraverse(list_p);


	ClearList(&list_p);
	printf("after clear,length:%d \n", ListLength(list_p));
	ListTraverse(list_p);

	//CreateList(&list_q, 3);//list_q在Mergelist中被释放,需重建
#ifndef _POINT_
	if (InsertList(list_p, 1, 3))
	{
		ListTraverse(list_p);
		printf(" 1 insert length:%d \n", ListLength(list_p));
	}
	if (InsertList(list_p, 3, 6))
	{
		ListTraverse(list_p);
		printf(" 2 insert length:%d \n", ListLength(list_p));
	}
	if (InsertList(list_p, ListLength(list_p) + 1, 5))
	{
		ListTraverse(list_p);
		printf(" 3 insert length:%d \n", ListLength(list_p));
	}

	if (InsertList(list_p, ListLength(list_p) + 2, 5))
	{
		ListTraverse(list_p);
		printf(" 4 insert length:%d \n", ListLength(list_p));
	}
	if (InsertList(list_p, ListLength(list_p) + 12, 5))
	{
		ListTraverse(list_p);
		printf(" 4 insert length:%d \n", ListLength(list_p));
	}
#else
	if (InsertList_p(&list_p, 1, 3))//边界测试
	{
		printf("1st insert length:%d \n", ListLength(list_p));
		ListTraverse(list_p);
	}
	if (InsertList_p(&list_p, 3, 6))
	{
		printf("2nd insert length:%d \n", ListLength(list_p));
		ListTraverse(list_p);
	}
	if (InsertList_p(&list_p, ListLength(list_p) + 1, 5))//边界测试
	{
		printf("3th insert length:%d \n", ListLength(list_p));
		ListTraverse(list_p);
	}
	if (DelList(&list_p, 1, &n))//边界测试
	{
		printf("del 1st num:%d\n", n);
		ListTraverse(list_p);
	}
	if (DelList(&list_p, ListLength(list_p), &m))//边界测试
	{
		printf("del last num:%d\n", m);
		ListTraverse(list_p);
	}
 	if (InsertList_p(&list_p, ListLength(list_p) + 2, 5)) //边界测试
	{
		printf("insert len+2 length:%d \n", ListLength(list_p));
		ListTraverse(list_p);
	}
#endif

	return 0;
}

int CreateList(LinkList *list, int n) //创建带表头的链表  从尾到头
{
	int i = 0;
	LinkList p;

	*list = (LinkList)malloc(sizeof(Node));//创建头结点
	if(!(*list))
		return ERROR;
	(*list)->next = NULL;

	for (i = 0; i < n; i++)
	{
		p = (LinkList)malloc(sizeof(Node));
		if (!p)
			return ERROR;
		
		printf("input data:");
		scanf_s("%d",&p->data);
		p->next = (*list)->next;
		(*list)->next = p;
	}
	return OK;
}

int ListTraverse(LinkList list)
{
	LinkList p = list->next;//指向第一个节点
	while(p)
	{
		printf("%d ",p->data);
		p = p->next;
	}
	printf("\n");

	return OK;
}

/*在第pos位置之前添加,1<=n<= length +1*/
int InsertList(LinkList list, int pos, int n) 
{
	int i = 0;
	LinkList p = list; //指向头
	LinkList temp;

	if(pos < 1)
		return ERROR;
	for (i = 0; i< pos-1 && p;i++) //使指针 指向 pos - 1 的位置, !p保证 pos-1 <=length+1
	{
		p = p->next;
	}//退出3中可能 (1)i == pos -1  正确 (2)p == null (3)兼有  (2)(3)为超过length+1
	if(!p || i != pos-1) 
	{
		printf("beyond the limit\n");
		return ERROR; //确认指针 指向 pos - 1 的位置
	}
	temp = (LinkList)malloc(sizeof(Node));
	if (!temp)
	{
		return ERROR;
	}
	temp->data = n;
	temp->next = p->next;
	p->next = temp;

	return OK;
}

int DelList(LinkList *list, int pos, int *n)
{
	int i;
	LinkList p = *list;//p指向标头
	LinkList q;
	
	if (pos < 1)
		return ERROR;
	for(i = 0; (i < pos-1)&&(p->next); i++) //指向pos-1
	{
		p = p->next;
		//边界检测
	}	
	if ((i != pos-1)||(!(p->next)))
		return ERROR;
	
	q = p->next;
	*n = q->data;
	p->next = q->next;
	free(q);

	return OK;
}

int ListLength(LinkList list)
{
	int length = 0;
	LinkList p = list;

	if (!list)//边界检测
		return ERROR;

	while (p->next)
	{
		length++;
		p = p->next; 
	}
	return length;
}

int InsertList_p(LinkList *list, int pos, int n) 
{
	int i = 0;
	LinkList *p = list; //指向头
	LinkList temp;

    LinkList q = *list;
	if (pos < 1)
	{
		return ERROR;
	}
	for (i = 0; i < pos-1 && q ;i++) //指向 pos - 1 的位置
	{
		q = q->next;	
	}
	if ( !q || i != pos-1 )
	{
		printf("beyond limit\n");
		return ERROR;
	}
	temp = (LinkList)malloc(sizeof(Node));
	temp->data = n;
	temp->next = q->next;
	q->next = temp;

	return OK;
}

int MergeList(LinkList *des_list, LinkList *src_list)//两列表有序 从小到大排列
{	
	LinkList des = *des_list;//指向头结点
	LinkList p_des = (*des_list)->next;//指向第一个结点
	LinkList p_src = (*src_list)->next;

	while(p_des && p_src)
	{
		if (p_des->data <= p_src->data)
		{
			des->next = p_des;
			des = des->next;
			p_des = p_des->next;
		}
		else
		{
			des->next = p_src;
			des = des->next;
			p_src = p_src->next;
		}	
	}
	des->next = p_des ? p_des : p_src;//
	free(*src_list);//释放源链表的头结点

	return OK;
}

int DestroyList(LinkList *list)//从表头开始释放
{
	LinkList *t_list = list;//*t_list为 标头
	LinkList p;

	while (*t_list)
	{
		p = (*t_list)->next;
		free(*t_list);
		*t_list = p;
	}
	*list = NULL;  //收尾,是list指向空

	return OK;
}

int ClearList(LinkList *list)//从第一个结点开始释放
{
	LinkList p = (*list)->next;//指向第一个节点
	LinkList q;

	while(p)
	{
		q = p->next;
		free(p);
		p = q;
	}
	(*list)->next = NULL;

	return OK;
}

int LocatePos(LinkList list, int pos, LinkList *des)//用des指向list中第pos个结点
{
	LinkList p = list;//p指向头结点
	int i = 0;

	if (pos < 1)
		return ERROR;
	while(p && i<pos)//p指向 pos位置,pos次
	{
		p = p->next;
		i++;
	}
	if(!p || i != pos)
		return ERROR;

	(*des)->next = p->next;
	(*des)->data = p->data;

	return OK;
}

int MakeNode(LinkList *node, ElemType e)
{
	*node = (LinkList)malloc(sizeof(Node));
	if (!*node)
		return ERROR;

	(*node)->next = NULL;
	(*node)->data = e;
	return OK;
}

int InsFirst(LinkList *list, LinkList p)//将p指向的结点添加至list第一个位置
{
	LinkList t_list = (*list)->next;//指向第一个节点
	(*list)->next = p;
	p->next = t_list;//p指向结点为第一结点

	return OK;
}

int DelFirst(LinkList list, LinkList p)//p删除第一个结点,并用p指向该结点
{
 	LinkList head = list;
	LinkList q = head->next;//p指向第一个节点
	if (!q)
		return ERROR;
	head->next = q->next;

	return OK;
}

测试结果:

小结:

 对比  int InsertList(LinkList list, int pos, int n);  与   int InsertList_p(LinkList *list, int pos, int n);

上例中对 链表进行插入操作时,既可以 传递 LinkList p_node变量--指向结点的指针,也可传递 LinkList *list指向 链表的指针。

理解不同传递参数的意义:

传递 LinkList p_node时,理解为 传递头结点的地址。  (LinkList == Node*)

传递 LinkList *list 时,理解为传递的为链表的地址。 (链表为指向头结点的指针/地址)

传递不同参数的目的:

获取参数拷贝,还是获取地址 修改该参数的内容。

抱歉!评论已关闭.