考研复习线性表之——链表

文章目录

  • 单链表
    • 存储结构
    • GetElem()
    • ListInsert()
    • createList(Linklist &L,int n)(头插法,尾插法)
    • 例题A,B是两个单链表,递增有序,归并A,B得到C,也是递增有序的
    • 单链表注意事项
  • 双链表
    • 存储结构
    • 尾插法建立双链表
    • 查找节点
    • 插入节点
    • 删除节点
  • 循环链表
  • 逆置问题(408重要考点)

单链表

存储结构

typedef struct node{
	int data;
	struct node *next;//定义指向后继节点的指针
}node,*Linklist;

GetElem()

void GetElem(Linklist L,int i,int &e){
	int j=1;
	node *p;
    p=L;
	while(p->next&&j<i)//j=i时跳出
	{
		p=p->next;
		j++;
	}
	if(!p||j>i) printf("error");
	e=p->data;
}

ListInsert()

 void ListInsert(Listlink &L,int i,int e)
{
	 int j=1;
	 Listlink *p=L;
	 while(p&&j<i-1){
	 	p=p->next;
	 	j++;
	 }
	 if(!p|j>i) printf("error");
	 Linklist *s;
	 s->data=e;
	 s->next=p->next;
	 p->next=s;
}

createList(Linklist &L,int n)(头插法,尾插法)

void createList(Linklist &L,int n)
{
	L=(Linklist)malloc(sizeof(node));
	L->next=NULL;//建立一个带头节点的单链表
	for(int i=0;i<n;i++){
		Linklist p=(Linklist)malloc(sizeof(node));//建立一个新节点
        printf("请输入第%d个节点",i);
		scanf("%d",&p->data);
		p->next=L->next;
		L->next=p;//头插法
	}
}

尾插法

void createList(Linklist &L,int n)
{
    node *q;
    node* p=(node*)malloc(sizeof(node));//建立一个新节点
	L=p;//p始终指向终端节点
	for(int i=0;i<n;i++){
		q=(node*)malloc(sizeof(node));//建立一个新节点
        printf("请输入第%d个节点",i+1);
		scanf("%d",&q->data);
		p->next=q;
		p=p->next;
	}
    p->next=NULL;
}

例题A,B是两个单链表,递增有序,归并A,B得到C,也是递增有序的

#include 
#include 
using namespace std;
typedef struct node{
	int data;
	struct node *next;//定义指向后继节点的指针
}node,*Linklist;
//void merge(Linklist A,Linklist B,Linklist &);
void merge(Linklist A,Linklist B,Linklist &C);
void merge(Linklist A,Linklist B,Linklist &C){
	Linklist q=A->next;
	Linklist p=B->next;
	Linklist r;//r是尾指针
    r=C=A;//A的头节点作为C的头节点
	//C->next=NULL;
	while(q&&p){
		if(q->data<=p->data)
		{
			r->next=q;
			r=q;
			q=q->next;
		}else{
			r->next=p;
			r=p;
			p=p->next;
		}
	}
	if(q!=NULL) r->next=q;
	if(p!=NULL) r->next=p;
    free(B);
}
void createList(Linklist &L,int n)
{
	//L=(Linklist)malloc(sizeof(node));
    node *q;
    node* p=(node*)malloc(sizeof(node));//建立一个新节点
	L=p;//p始终指向终端节点
	for(int i=0;i<n;i++){
		q=(node*)malloc(sizeof(node));//建立一个新节点
        printf("请输入第%d个节点",i+1);
		scanf("%d",&q->data);
		p->next=q;
		p=p->next;
	}
    p->next=NULL;
}
void GetElem(Linklist L,int i,int &e){
	int j=1;
	node *p;
    p=L;
	while(p->next&&j<i)//j=i时跳出
	{
		p=p->next;
		j++;
	}
	if(!p||j>i) printf("error");
	e=p->data;
}
int main()
{
    Linklist A;
    A=(Linklist)malloc(sizeof(node));
    Linklist B;
    B=(Linklist)malloc(sizeof(node));
    Linklist C;
    C=(Linklist)malloc(sizeof(node));
    createList(A,3);
    createList(B,2);
    createList(C,0);
    merge(A,B,C);
    for(int i=2;i<7;i++){
        int a;
        GetElem(C,i,a);
        printf("%d",a);
    }
    printf("\n");
}

单链表注意事项

  1. 刚开始的时候会报错 Segmentation fault: 11,经过查询是因为mac系统对于指针是否分配空间比较严格。所以在调用函数之前必须给指针malloc。
  2. 输出链表总是在开头多输出一个0,是因为没有注意到 把头指针也输出了,头指针没有赋值应该默认值是0.,输出的时候注意一下不要从头指针开始。

双链表

使用单链表只能从一个方向遍历,如果要找前驱节点需要重新便利,所以引入了双链表。
双链表与单链表的区别在于,每个节点不光有指向下一个节点的指针,还有指向上一个节点的指针(prior)这样插入和删除的时候就有很大的不同了。要同时删除两个方向的指针。

存储结构

typedef struct DLnode{
	struct node* prior;
	struct node* next;
	int data;
}

尾插法建立双链表

void createList(Linklist &L,int n)
{
	//L=(Linklist)malloc(sizeof(node));
    DLnode *q;
    DLnode* p=(DLnode*)malloc(sizeof(node));//建立一个新节点
	L=p;//p始终指向终端节点
	for(int i=0;i<n;i++){
		q=(DLnode*)malloc(sizeof(DLnode));//建立一个新节点
        printf("请输入第%d个节点",i+1);
		scanf("%d",&q->data);
		p->next=q;
		q->prior=p;
		p=p->next;
	}
    p->next=NULL;
}

查找节点

DLnode* GetElem(DLnode L;int i){
	p=L->next;
	int j=1;//计数器
	while(p&&j<i){
		p=p->next;
		j++;
	}
	if(p||j>i) erroe;
	return p;
}

插入节点

void ListInsert(DLnode &L,int i,int e){
	//找到插入位置指针p
	DLnode p=(DLnode*)malloc(sizeof(DLnode));
	p=GetElem(L,i);
	DLnode s=(DLnode*)malloc(sizeof(DLnode));
	s->data=e;
	s->prior=p->prior;
	p->prior->next=s;
	s->next=p;
	p->prior=s;
}

删除节点

void DeleteInsert(DLnode &L,int i,int e){
	//找到插入位置指针p
	DLnode p=(DLnode*)malloc(sizeof(DLnode));
	p=GetElem(L,i);
	p->prior->next=p->next;
	p->next->prior=p->prior;
	free(p);
}

循环链表

循环链表是单链表和双链表的进化版,只需要在终端节点和头节点之间建立联系即可。
设p为终端节点,p->next=head;
如果是循环双链表 加上head->prior=p;

逆置问题(408重要考点)

给定一个线性表,如何将其中的元素逆置?
解析:设两个整型变量i,j i指向表头,j指向表尾,一边交换元素一边相向而行。

你可能感兴趣的:(数据结构)