基础数据结构 链表、栈、队列

数据结构是程序设计中一个非常重要的部分,基本的数据结构包括链表、栈和队列,当然高级一点的还有树、图等,实际上链表、栈和队列都是线性表,只是在操作和表示方式上有所不同,线性表用顺序结构表示就是顺序表,用链结构表示就是链表,如果对线性表的操作加以限制,只能有在表尾进行插入和删除元素,这就变成栈了,如果只能允许元素从表尾插入,表头删除,这就变成队列了。

链表

/*
 *	数据结构 链表
 *	链式结构
 */

#include <iostream>
using namespace std;

enum Status
{
	ERROR = -1,
	OK = 0
};

typedef int ElemType;
//定义链表的节点
typedef struct LNode
{
	ElemType data;
	LNode *next;
} LNode, *LinkList;

/*
 *	创建一个长度为size的单链表,并返回链表头结点
 *	从后先前不断插入新的元素,每次新元素都添加到头结点后面
 */
LinkList createList(int size)
{
	if (size <= 0)
		return NULL;

	//定义头节点
	LinkList list = new LNode[1];
	list->next = NULL;

	for (int i=size; i>=1; i--)
	{
		LNode *node = new LNode[1];
		cin>>node->data;
		node->next = list->next;
		list->next = node;
	}

	return list;
}

/*
 *	从链表 list 中取第 pos 个元素,并将元素值付给 elem
 */
Status getElem(LinkList list, int pos, ElemType &elem)
{
	if (! list)
	{
		return Status::ERROR;
	}

	LNode *p = list->next;
	int j = 1;

	while (p && j<pos)
	{
		p = p->next;
		j++;
	}
	//判断是否存在第 pos 个元素,或者 pos 值输入不合法(负值或0)
	if (! p || j > pos)
	{
		return Status::ERROR;
	}

	elem = p->data;
	return Status::OK;
}

/*
 *	将元素elem插入到链表list中的第pos个位置
 *	要想在第pos个位置插入元素,需要先找到第
 *	pos-1个位置
 */
Status insertList(LinkList list, int pos, ElemType elem)
{
	LNode *p = list;
	int j = 0;
	while (p && j<pos-1)
	{
		p = p->next;
		j++;
	}

	if (! p || j > pos-1)
	{
		return Status::ERROR;
	}

	LNode *node = new LNode[1];
	node->data = elem;
	node->next = p->next;
	p->next = node;

	return Status::OK;
}

/*
 *	从链表list中删除第pos个元素,并将该元素值赋给elem
 *	首先找到第pos-1个元素
 */
Status deleteList(LinkList list, int pos, ElemType &elem)
{
	LNode *p = list;
	int j = 0;
	//找到第 pos-1 个元素
	while (p && j<pos-1)
	{
		p = p->next;
		j++;
	}

	if (! p || j>pos-1 || ! p->next)
	{
		return Status::ERROR;
	}

	LNode *q = p->next;
	elem = q->data;
	p->next = q->next;
	delete q;

	return Status::OK;
}

/*
 *	合并链表list1和list2,并返回合并后的链表头结点
 *	list1和list2均是按值非递减排列
 */
LinkList mergeList(LinkList list1, LinkList list2)
{
	LinkList list;

	if (! list1 || ! list2)
	{
		list = list2==NULL ? list1 : list2;
		return list;
	}

	list = list1;

	LinkList p = list, p1 = list1->next, p2 = list2->next;
	while (p1 && p2)
	{
		if (p1->data <= p2->data)
		{
			p->next = p1;
			p1 = p1->next;
		} else {
			p->next = p2;
			p2 = p2->next;
		}
		p = p->next;
	}

	p->next = p1 ? p1 : p2;
	delete list2;

	return list;
}

void printList(LinkList list, char *str="")
{
	cout<<str<<endl;

	if (list == NULL)
		return;

	LNode *p = list->next;
	while (p)
	{
		cout<<p->data<<" ";
		p = p->next;
	}
	cout<<endl;
}

void destroyList(LinkList list)
{
	if (! list)
	{
		return;
	}

	while (list->next)
	{
		LNode *p = list->next;
		list->next = p->next;
		delete p;
	}

	delete list;
}

/*
 *	数据结构 栈
 *	顺序结构
 */

#include <iostream>
#include <cstdlib>
using namespace std;

#define STACK_INIT_SIZE 100
#define STACK_INCREMENT 10

enum Status
{
	ERROR = -1,
	OK = 0,
	TRUE = 1,
	FALSE = 2
};

typedef int ElemType;

typedef struct Stack
{
	ElemType *top;//指向栈顶元素的上一个位置
	ElemType *base;//指向栈底元素
	int size;//栈空间的长度
} Stack;

/*
 *	初始化栈操作
 */
Status initStack(Stack* &stack)
{//此处的形参必须使用指针的引用,因为可能会改变指针本身的值,而不是其指向的对象的值
	if (! stack)
	{
		stack = (Stack*)malloc(sizeof(Stack));
	}
	stack->base = (ElemType*)malloc(STACK_INIT_SIZE * sizeof(ElemType));
	if (! stack->base)
	{
		return Status::ERROR;
	}

	stack->top = stack->base;
	stack->size = STACK_INIT_SIZE;

	return Status::OK;
}

/*
 *	获取栈顶元素
 */
Status getTop(Stack *stack, ElemType &elem)
{
	if (! stack || stack->base == stack->top)
	{
		return Status::ERROR;
	}

	elem = *(stack->top-1);
	return Status::OK;
}

/*
 * 压入新的元素到栈顶
 */
Status push(Stack *stack, ElemType elem)
{
	if (! stack)
	{
		return Status::ERROR;
	}
	//先判断栈是否满
	if (stack->top - stack->base >= stack->size)
	{
		stack->base = (ElemType*)realloc(stack->base, (stack->size+STACK_INCREMENT)*sizeof(ElemType));
		if (! stack->base)
		{
			return Status::ERROR;
		}
		stack->top = stack->base + stack->size;
		stack->size += STACK_INCREMENT;
	}

	*stack->top = elem;
	stack->top++;

	return Status::OK;
}

/*
 *	判断栈是否为空
 */
Status isEmpty(Stack *stack)
{
	if (! stack || stack->base == stack->top)
	{
		return Status::TRUE;
	}

	return Status::FALSE;
}

/*
 *	弹出栈顶元素
 */
Status pop(Stack* stack, ElemType &elem)
{
	if (isEmpty(stack) == Status::TRUE)
	{
		return Status::ERROR;
	}

	stack->top--;
	elem = *stack->top;

	return Status::OK;
}

Status destroyStack(Stack *stack)
{
	if (! stack)
		return Status::OK;

	if (stack->base)
	{
		free(stack->base);
		stack->base = stack->top = NULL;
	}

	return Status::OK;
}

void printStack(Stack *stack, char *str = "")
{
	if (isEmpty(stack) == Status::TRUE)
	{
		return;
	}
	cout<<str<<endl;
	ElemType *p = stack->base;
	while (p != stack->top)
	{
		cout<<*p<<" ";
		p++;
	}
	cout<<endl;
}

队列

/*
 *	数据结构 队列
 *	链式结构
 */

#include <iostream>
using namespace std;

enum Status
{
	ERROR = -1,
	OK = 0,
	TRUE = 1,
	FALSE = 2
};

typedef int ElemType;

typedef struct QNode
{
	ElemType data;
	QNode* next;
} QNode;

typedef struct LinkQueue
{
	QNode* front;
	QNode* rear;
} LinkQueue;

/*
 *	初始化队列
 */
Status initQueue(LinkQueue* &queue)
{
	if (! queue)
	{
		queue = (LinkQueue*)malloc(sizeof(LinkQueue));
	}

	queue->front = queue->rear = (QNode*)malloc(sizeof(QNode));
	if (! queue->front)
	{
		return Status::ERROR;
	}

	queue->front->next = NULL;

	return Status::OK;
}

/*
 *	入队
 */
Status enQueue(LinkQueue* queue, ElemType elem)
{
	if (! queue)
	{
		return Status::ERROR;
	}

	QNode* node = (QNode*)malloc(sizeof(QNode));
	if (! node)
	{
		return Status::ERROR;
	}

	node->data = elem;
	node->next = NULL;
	queue->rear->next = node;
	queue->rear = node;

	return Status::OK;
}

/*
 *	判断队列是否为空
 */
Status isEmpty(LinkQueue* queue)
{
	if (! queue || queue->front == queue->rear)
		return Status::TRUE;

	return Status::FALSE;
}

/*
 *	出队
 */
Status deQueue(LinkQueue* queue, ElemType &elem)
{
	if (isEmpty(queue) == Status::TRUE)
	{
		return Status::ERROR;
	}
	QNode* p = queue->front->next;
	elem = p->data;
	queue->front->next = p->next;
	if (queue->rear == p)
		queue->rear = queue->front;
	free(p);

	return Status::OK;
}

/*
 *	销毁队列
 */
Status destroyQueue(LinkQueue* queue)
{
	if (! queue)
		return Status::OK;

	while (queue->front)
	{
		queue->rear = queue->front->next;
		free(queue->front);
		queue->front = queue->rear;
	}

	return Status::OK;
}

void printQueue(LinkQueue* queue, char* str)
{
	if (isEmpty(queue) == Status::TRUE)
	{
		return;
	}

	cout<<str<<endl;

	QNode* p = queue->front->next;
	while (p)
	{
		cout<<p->data<<" ";
		p = p->next;
	}
	cout<<endl;
}
/*
 *	数据结构 队列
 *	顺序结构,循环队列
 *	因为队列是从队头删除元素,从队尾插入元素
 *	在删除元素之后,不可能让队列中的所有元素都向前移动
 *	只能是将队头指针向后收缩一个位置,则前面空出了空间,为了使用这些空间
 *	就需要使用循环队列,将队头和队尾连接起来,这样真正的队头并不一定就是申请
 *	到的顺序空间的首地址,队尾也并不一定就是顺序空间的尾地址,所以在循环队列满了之后
 *	无法使用realloc重新分配新的空间使用,因为这样会打破原来的队列结构,新的队列空间可能
 *	会插入到队列的任意位置,对队列的头尾操作同样无法进行,所以只能给循环队列设置一个最大
 *	队列长度,无法动态分配,如果最大长度不确定,则使用链式队列较好
 */

#include <iostream>
using namespace std;

#define MAXSIZE 100

enum Status
{
	ERROR = -1,
	OK = 0,
	TRUE = 1,
	FALSE = 2
};

typedef int ElemType;

typedef struct CircleQueue
{
	ElemType* base;
	int front;
	int rear;
} CircleQueue;

/*
 *	初始化队列
 */
Status initQueue(CircleQueue* &queue)
{
	if (! queue)
	{
		queue = (CircleQueue*)malloc(sizeof(CircleQueue));
	}
	if (! queue)
		return Status::ERROR;

	queue->base = (ElemType*)malloc(MAXSIZE * sizeof(ElemType));
	if (! queue->base)
	{
		return Status::ERROR;
	}

	queue->front = queue->rear = 0;

	return Status::OK;
}

/*
 *	获取队列的长度
 */
int getLength(CircleQueue* queue)
{
	if (! queue)
	{
		return 0;
	}

	return (queue->rear - queue->front + MAXSIZE) % MAXSIZE;
}

/*
 *	入队
 */
Status enQueue(CircleQueue* queue, ElemType elem)
{//预留一个空间不放元素,以区别队列满和空的标志
	if (! queue || (queue->rear+1)%MAXSIZE == queue->front)
	{
		return Status::ERROR;
	}

	queue->base[queue->rear] = elem;
	queue->rear = (queue->rear + 1) % MAXSIZE;

	return Status::OK;
}

/*
 *	判断队列是否为空
 */
Status isEmpty(CircleQueue* queue)
{
	if (! queue || ! queue->base || queue->front == queue->rear)
	{
		return Status::TRUE;
	}
	return Status::FALSE;
}

/*
 *	出队
 */
Status deQueue(CircleQueue* queue, ElemType &elem)
{
	if (isEmpty(queue) == Status::TRUE)
	{
		return Status::ERROR;
	}

	elem = queue->base[queue->front];
	queue->front = (queue->front + 1) % MAXSIZE;

	return Status::OK;
}

/*
 *	销毁队列
 */
Status destroyQueue(CircleQueue* queue)
{
	if (! queue)
	{
		return Status::OK;
	}

	if (queue->base)
	{
		free(queue->base);
		queue->base = NULL;
	}

	return Status::OK;
}

void printQueue(CircleQueue* queue, char* str)
{
	if (isEmpty(queue) == Status::TRUE)
		return;

	cout<<str<<endl;

	int pos = queue->front;
	while (pos != queue->rear)
	{
		cout<<queue->base[pos]<<" ";
		pos = (pos+1)%MAXSIZE;
	}
	cout<<endl;
}
时间: 2024-10-12 21:50:54

基础数据结构 链表、栈、队列的相关文章

数据结构录 之 链表&amp;栈&amp;队列

三种基本的数据结构,来稍微说一下. 首先链表,这个几乎每本C++的语言书都会说的,直接看书上说的就好. 链表就是一个链,每一个都有一个指针指向下一个,然后这样串了起来.然后可以从头开始找,一直找到尾巴.然后对于某个数据点,都可以删除,只需要让他前面那个指向他后面那个,这样从头开始找的时候就找不到这个点了...在这个点之后添加一个点也是这样,直接让这个点指向那个新的,然后让新的指向原来这个点指向的后一个... 可以想象就是一个个点,然后第一个指向第二个,第二个指向第三个...就像是一条长长的链一样

【图解数据结构】 栈&amp;队列

[TOC] 勤于总结,持续输出! 1.栈 1.1栈的定义 栈(stack)是限定在表尾进行插入和删除的操作的线性表. 我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不包含任何数据元素的栈称为空栈.栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构. 栈的插入操作,叫做进栈,也称压栈.入栈. 栈的删除操作,叫做出栈,也称弹栈. 1.2栈的顺序存储结构及实现 既然栈是线性表的特例,那么栈的顺序存储其实也是线性表顺序存储的简化. 用数组实现

线性表的比较和抽象数据结构(栈&amp;队列)的实现方式

链表的两种底层结构 1.ArrayList实现单链表(其实就是一个顺序数组) ArrayList其实就是一组长度可变的数组,当实例化了一个ArrayList,该数据也被实例化了,当向集合中添加对象时,数组的大小也随着改变,这样它所带来的有优点是快速的随机访问(数组可以利用下标直接访问),即使访问每个元素所带来的性能问题也是很小的,但缺点就是想其中添加或删除对象速度慢,当你创建的数组是不确定其容量,所以当我们改变这个数组时就必须在内存中做很多的处理,如你想要数组中任意两个元素中间添加对象,那么在内

基础数据结构-链表

思维导图 1. 熟悉结构 首先我们要知道链表的结构以及每个节点的结构,这是我们手写链表的第一步,也是学习链表的第一步.我们知道,每个链表时这样表示的: 那每个节点结构是由数据域和指针域组成,数据域是存放数据的,而指针域存放下一结点的地址. 我们可以通过数据域访问到我们要的数据,而通过指针域访问到当前结点以后的结点,那么将这些结点串起来,就是一个链表. 那么用代码怎么来表示呢? 我们通常会用到函数,我们如果将一个函数抽象成一个结点,那么我们给函数添加两个属性,一个属性是存放数据的属性data,另一

算法系列(六)数据结构之表队列和栈

在http://blog.csdn.net/robertcpp/article/details/51559333一文中,我们讲了排序,这一章来介绍一下基本数据结构:表.队列.栈和它们的简单实现 一.表ADT 1.数组实现顺序表 通过对数组操作,来直接对表进行增删查改操作,这种线性表查找某个位置的元素花费的时间为O(1),但是插入删除元素花费的时间为O(n),如果对表的操作更多的是访问操作,那么选择这种实现更为合适. 下面是一个简单实现 package com.algorithm.list; im

数据结构之栈和队列及其Java实现

栈和队列是数据结构中非常常见又非常基础的线性表,在某些场合栈和队列使用很多,因此本篇主要介绍栈和队列,并用Java实现基本的栈和队列,同时用两个栈实现队列和用两个队列实现栈. 栈:栈是一种基于"后进先出"策略的线性表.在插入时(入栈),最先插入的元素在栈尾,最后插入的元素在栈顶:在删除时(出栈),最后插入的元素先出栈,最先插入的元素最后出栈.由此可见,对栈的插入和删除操作都是在栈顶位置进行的. 在Java中,提供了一个类Stack<E>来实现栈的这些特性,并提供了一些常用的

【转载】浅谈算法和数据结构: 一 栈和队列

作者:yangecnu(yangecnu's Blog on 博客园) 出处:http://www.cnblogs.com/yangecnu/ 最近晚上在家里看Algorithms,4th Edition,我买的英文版,觉得这本书写的比较浅显易懂,而且“图码并茂”,趁着这次机会打算好好学习做做笔记,这样也会印象深刻,这也是写这一系列文章的原因.另外普林斯顿大学在Coursera 上也有这本书同步的公开课,还有另外一门算法分析课,这门课程的作者也是这本书的作者,两门课都挺不错的. 计算机程序离不开

浅谈算法和数据结构: 一 栈和队列

最近晚上在家里看Algorithems,4th Edition,我买的英文版,觉得这本书写的比较浅显易懂,而且"图码并茂",趁着这次机会打算好好学习做做笔记,这样也会印象深刻,这也是写这一系列文章的原因.另外普林斯顿大学在Coursera 上也有这本书同步的公开课,还有另外一门算法分析课,这门课程的作者也是这本书的作者,两门课都挺不错的. 计算机程序离不开算法和数据结构,本文简单介绍栈(Stack)和队列(Queue)的实现,.NET中与之相关的数据结构,典型应用等,希望能加深自己对这

&lt;数据结构与算法分析 C++描述&gt; 表/栈/队列

这一章主要内容: * 抽象数据类型(ADT)的概念 * 实现表/栈/队列 * 了解这三个数据结构的应用场景 1. ADT ADT: abstract data type, 是抽象的数学模型,在该模型上定义了一系列的操作.使用它的人,不需要了解它的存储方式,只关心它的逻辑特征.可以使用三元组的方法来表示(D,S,P),D是数据对象,S是数据之间的关系,P是对数据的基本操作,具体介绍,可以参考帖子:点击打开链接 2. 表ADT 表的数据自然是单个元素,而元素之间的关系是前驱与后继,操作包括查找/插入