看数据结构写代码(7)具有实用意义的双向链表

今天写到太晚了,还好明天不上班。

直接上代码:

// LinkList.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdlib.h>

typedef int ElementType;
enum E_STATE
{
	E_STATE_ERROR = 0,
	E_STATE_OK = 1,
};
//具有实用意义的链表,比书里的例子多了一个 前驱指针,因为觉得链表 可以指向 链表的尾部,但不可以 获取前驱,没什么意义

struct LinkNode
{
	ElementType data;
	LinkNode * next;
	LinkNode * pre;
};
//链表 指向 头指针和 尾指针
struct LinkList
{
	LinkNode * head;
	LinkNode * tail;
	int len;
};

LinkNode * makeNode(ElementType data){
	LinkNode * newNode = (LinkNode *) malloc(sizeof(LinkNode));
	if (newNode == NULL)
	{
		return NULL;;
	}
	//设置新节点
	newNode->next = NULL;
	newNode->pre = NULL;
	newNode->data = data;
	return newNode;
}

E_STATE listInit(LinkList * l){
	LinkNode * pHead = (LinkNode *)malloc(sizeof(LinkNode));
	if (pHead == NULL)
	{
		return E_STATE_ERROR;
	}
	pHead->next = NULL;
	pHead->pre = NULL;
	l->head = l->tail = pHead;
	l->len = 0;
	return E_STATE_OK;
}

void listClear(LinkList * l){
	LinkNode * head = l->head;
	LinkNode * next = head->next;
	//在判断是否到了链表的尾部的时候,比 head != l-> tail 方便
	while (next != NULL)//后继不为空
	{
		LinkNode * freeNode = next;
		next = next->next;
		free(freeNode);
	}
	//重置默认参数
	l->tail = l->head;
	l->len = 0;
}

void listDestory(LinkList *l){
	//重置为空表
	listClear(l);
	//释放头指针
	free(l->head);
	l->head = l->tail = NULL;
}

//插入一个新的尾节点
E_STATE listInsertTail(LinkList * l,ElementType data){
	LinkNode * node = makeNode(data);
	if (node == NULL)
	{
		return E_STATE_ERROR;
	}
	//设置新的尾节点
	node->next = NULL;
	node->pre = l->tail;
	l->tail->next = node;
	l->len++;
	l->tail = node;
	return E_STATE_OK;
}

void listRemoveTail(LinkList * l){
	//尾指针的前驱
	LinkNode * tailPre = l->tail->pre;
	//表空时,尾指针 和头指针 是相等的
	if (l->head != l->tail)//表不为空
	{
		LinkNode * freeNode = tailPre->next;
		tailPre->next = NULL;
		free(freeNode);
		l->len--;
		l->tail = tailPre;
	}
}

//在 node 节点前插入一个 新节点
E_STATE listInsertBefore(LinkList * l,LinkNode * node,ElementType data){
	LinkNode * newNode = makeNode(data);
	if (newNode == NULL)
	{
		return E_STATE_ERROR;
	}
	//设置新节点
	LinkNode * pre = node->pre;
	newNode->next = node;
	newNode->pre = pre;
	//设置前驱节点
	pre->next = newNode;
	//设置后继节点
	node->pre = newNode;
	l->len ++;
	return E_STATE_OK;
}
//在节点后插入
E_STATE listInsertAfter(LinkList * l,LinkNode * node,ElementType data){
	LinkNode * newNode = makeNode(data);
	if (newNode == NULL)
	{
		return E_STATE_ERROR;
	}
	//设置新节点
	LinkNode * nodeNext = node->next;
	newNode->next = nodeNext;
	newNode->pre = node;
	//设置前驱节点
	node->next = newNode;
	//设置后继节点
	if (nodeNext != NULL)
	{
		nodeNext->pre = newNode;
	}
	else//node 为尾指针节点
	{
		l->tail = newNode;
	}
	l->len++;
	return E_STATE_OK;
}

int listLen(LinkList l){
	return l.len;
}

bool listEmpty(LinkList l){
	return l.len == 0 ? true : false;
}
//第一个节点
LinkNode * listFirstNode(LinkList l){
	return l.head->next;
}
//最后一个节点
LinkNode * listLastNode(LinkList l){
	return l.head == l.tail ? NULL : l.tail;
}
//节点的前驱
LinkNode * listPreNode(LinkList l,LinkNode node){
	LinkNode * pre = node.pre;
	return pre == l.head ? NULL : pre;
}

LinkNode * listNextNode(LinkList l,LinkNode  node){
	return node.next;
}

void listTraverse(LinkList l){
	LinkNode * next = l.head->next;
	printf("----------------正序遍历开始--------------------------\n");
	while (next)
	{
		printf("----%d-----\n",next->data);
		next = next->next;
	}
	printf("-----------------正序遍历结束-------------------------\n");
}
//逆序
void listReverseTraverse(LinkList l){
	LinkNode * pre = l.tail;
	printf("-------------------逆序遍历开始-----------------------\n");
	while (pre != l.head)
	{
		printf("----%d-----\n",pre->data);
		pre = pre->pre;
	}
	printf("-------------------逆序遍历结束-----------------------\n");
}



int _tmain(int argc, _TCHAR* argv[])
{
	LinkList list;
	listInit(&list);
	for (int i = 1; i < 10; i++)
	{
		listInsertTail(&list,i);
	}
	listRemoveTail(&list);
	listRemoveTail(&list);
	LinkNode * pFirstNode = listFirstNode(list);
	listInsertBefore(&list,pFirstNode,66);
	LinkNode * pLastNode = listLastNode(list);
	listInsertAfter(&list,pLastNode,99);
	listTraverse(list);
	LinkNode * preNode = listPreNode(list,*pFirstNode);
	LinkNode * nextNode = listNextNode(list,*pLastNode);
	printf("%d 前继 : %d, %d 后继 : %d\n",pFirstNode->data,preNode->data,pLastNode->data,nextNode->data);
	printf("表长:%d\n",listLen(list));
	listReverseTraverse(list);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值