链表(linked list):
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
链式存储结构特点:
1.用任意一组存储单元存储线性表中的数据元素;
2.这组存储单元可以数连续的也可以是不连续的;
3.每个数据元素除了存储数据外,还要存储前驱、后继元素的地址。
单链表
n个节点按链式存储结构存储,每个节点只包含一个指针域。
线性表的单链表存储结构
typedef int DataType; //定义数据元素类型为整型
typedef struct Node{
DateType data; //数据域
struct Node *next; //指针域
}Node;
基本操作:
1.获取指定位置的元素
Node* getptr(Node* head, int pos){
Node *p = head;
if(p == NULL || pos ==0) //链表为空或获取链表的第一个节点
return head;
for(int i=0; p&&i<pos; i++) //p不为零时,i从0开始循环查找
p = p->next;
return p;
}
2.获取单链表中的节点个数
int getSize(Node* head){
int size = 0;
Node* p = head;
while(p){
size++;
p = p->next;
}
return size;
}
3.单链表插入(空表、头部)
bool insert(Node** head, int position, DateType d){
//空表 、插入位置不合理
if(position<0 || position>getSize(*head))
return false;
Node *node = (Node*)malloc(sizeof(Node));//分配存储空间
node->data = d; //数据域等于d
node->next = NULL; //指针域为空
//头部
if(position == 0)
{
node->next = *head;
*head = node;
return true;
}
//中间或尾部
Node *p = getptr(*head, position-1);
Node* r = p->next;
node->next = r;
p->next = node;
return true;
}
//用法举例:insert(&head, 1, 10);
4.单链表删除(头结点)
bool erase(Node** head, int pos){
//空表 、删除位置不合理
if(pos<0 || pos>= getSize(*head))
return false;
Node *p = *head;
//头结点
if(pos == 0){
*head = (*head)->next;
free(p);
p = NULL;
return true;
}
//中间或尾部
p = getptr(*head, pos-1);
Node *q = p->next;
p->next = q->next;
free(q);
q = NULL;
return true;
}
//用法举例: erase(&head, 1);
5.将两个线性链表合并
void union(Node *a, Node *b){
Node *p = a;
while(p->next)
p->next;
p->next = b;
}
6.将线性表倒置
void reverse(Node **head){
Node *p = *head;
Node *q = p->next;
if(q == NULL)
return;
Node *r = q->next;
if(p == *head)
p->next = NULL;
while(true){
q->next = p;
if(r == NULL){
*head = q;
break;
}
else{
p = q;
q = r;
r = r->next;
}
}
}
7.线性表的遍历
void trave(Node *head, void(*fun)(DateType)){
Node *p = head;
while(p){
fun(p->data);
p = p->next;
}
}
void printf(DateType d){
printf("%d\n", d);
}
单循环链表
循环链表:将单链表中最后一个节点的指针域由空改为指向第一个节点,使整个单链表形成一个环。
线性表单循环链表存储结构:
typedef int DataType;
typedef struct Node{
Datatype data;
struct Node *next;
}Node;
基本操作:
1.获取单循环链表中的节点个数
int getSize(Node* rear){
int size = 0;
if(rear){ //rear为尾指针
Node* p = rear->next;
while(p != rear){
size++;
p = p->next;
}
size++;
}
return size;
}
2.获取指定位置的元素
Node* getptr(Node* rear, int pos){
if(rear == NULL)
return rear;
if(pos >= getSize(rear))
return NULL;
Node *p = rear->next;
for(int i=0; i<pos; i++) //p不为零时,i从0开始循环查找
p = p->next;
return p;
}
3.单循环链表插入(空结点、头结点)
bool insert(Node** rear, int position, DateType d){
if(position<0 || position>getSize(*rear))
return false;
Node *node = (Node*)malloc(sizeof(Node));//分配存储空间
node->data = d; //数据域等于d
node->next = NULL; //指针域为空
if(position == 0)
{
if(*rear == NULL){
node -> next = node;
*rear = node;
}
else{
node->next = (*rear)->next;
(*rear)->next = node;
}
return true;
}
Node *p = getptr(*head, position-1);
Node* r = p->next;
node->next = r;
p->next = node;
if(*rear == p)
*rear = node;
return true;
}
4.单循环链表删除(头结点)
bool erase(Node** rear, int pos){
if(*rear==NULL || pos<0 || pos>= getSize(*rear))
return false;
Node *p = (*pear)->next;
//头结点
if(pos == 0){
(*rear)->next = p->next;
free(p);
p = NULL;
return true;
}
//中间和尾部
p = getptr(*head, pos-1);
Node *q = p->next;
p->next = q->next;
if(q == rear)
rear = p;
free(q);
q = NULL;
return true;
}