数据结构 单链表

  1. 线性链表
  2. 静态链表(数组)/动态链表(malloc)
  3. 循环链表
  4. 双向链表/单链表
    1 线性链表的基本操作
    顺序存储方式的优点:
    1)随机存取
    2)不需要额外增加空间以表示结点间的逻辑关系
    缺点:
    1)插入删除效率低
    2)只能利用连续空间,不能利用小块空间
    3)静态存储分配。表长变化大时难以确定表长的规模
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define OVERFLOW -2

using namespace std;

typedef int Elemtype;
typedef struct node{
Elemtype data;
struct node *next;
}node,*linklist;

//建立单链表
//1.头插 2.尾插
void createList_L(linklist &l){
l=(linklist )malloc(sizeof(node));
linklist p=l,q;
int x;
scanf ("%d",&x);
while (x!=-999){
q=(linklist )malloc(sizeof(node));
q->data=x;
p->next=q;
p=q;
scanf ("%d",&x);
}
q->next=NULL;
}
//算法2.11
void createList_Lhead(linklist &l){
l=(linklist )malloc(sizeof(node));
linklist p;
l->next=NULL;
int x;
scanf ("%d",&x);
while (x!=-999){
p=(linklist )malloc(sizeof(node));
p->data=x;
p->next=l->next;
l->next=p;
scanf ("%d",&x);
}
}
void displayList_L(linklist &l){
linklist p=l->next;
while (p!=NULL){
printf ("%d ",p->data);
p=p->next;
}
printf ("\n");
}
//查找运算
//1. 按照序号查找 2、按值查找
linklist getElem(linklist &l,int i){
int j=1;
linklist p=l->next;
while (p!=NULL&&j<i){
p=p->next;
j++;
}
return p;
}
linklist getElem_2(linklist &l,Elemtype e){
linklist p=l->next;
while (p!=NULL&&p->data!=e){
p=p->next;
}
if (!p){
printf("没有该元素\n");
return NULL;//返回值类型为指针
}
return p;
}

int listLength(linklist &l){
int count =0;
linklist p=l->next;
while (p){
p=p->next;
count ++;
}
return count;
}
//插入运算
//1.指定节点前、后 2.指定位置前、后
void listInsert_Lafter(linklist &p,Elemtype e){
linklist q;
q=(linklist )malloc (sizeof(node));
q->data=e;
q->next=p->next;
p->next=q;
}
void listInsert_Lbefore(linklist &l,linklist p,Elemtype e){
linklist q=l;
while (q->next!=p) q=q->next;
listInsert_Lafter(q,e);
}
void listInsert_Lbefore_2(linklist &l,linklist p,Elemtype e){
//仍然将Q插到P的后面,然后交换数据域!很聪明的前插方式,不用循环查找前驱了
linklist q;
q=(linklist )malloc (sizeof(node));
q->next=p->next;
p->next=q;
q->data=p->data;
p->data=e;
}
//在第i个元素之前插入e
int listInsert_L_i(linklist &l,int i,Elemtype e){
int j=0;//必须从头结点开始
linklist p=l;
//if (i<1||i>listLength(l)){
//printf("position error !\n");
//return 0;
//}
while (p&&j<i-1) {
//为什么这里是P?因为I可以是1--length+1
p=p->next;
j++;
}
if (!p||j>i-1){
//p为空是i太大,j>i-1是i太小
printf("position error \n");
return 0;
}
linklist q;
q=(linklist )malloc (sizeof(node));
q->data=e;
q->next=p->next;
p->next=q;
return 1;
}
//在值为y的结点前插入e
int listInsert_L_y(linklist &l,Elemtype y,Elemtype e){
linklist p=l;
while (p->next&&p->next->data!=y){
//如果P->next为空则Y元素必定不存在,注意这里与上一个插入的区别
p=p->next;
}
if (!p){
printf ("元素不存在\n");
return 0;
}
linklist q;
q=(linklist )malloc (sizeof(node));
q->data=e;
q->next=p->next;
p->next=q;

}
//删除
//1、给定结点2、给定位置
//注意:1、被删除结点是否存在2、释放存储空间
int listDelete_L(linklist &l,linklist &p){
linklist q=l;
while (q&&q->next!=p) q=q->next;
if (!q) {
printf ("结点不存在\n");
return 0;
}
q->next=p->next;
free(p);
return 1;
}
int listDelete_L_i(linklist &l,int i,Elemtype &e){
linklist p=l;
int j=0;
while (p->next&&j<i-1){
    //查找第I-1个结点
p=p->next;
j++;
}
if (!p->next||j>i-1){
printf ("position error\n");
return 0;
}
linklist q=p->next;
p->next=q->next;
e=q->data;
free(q);
return 1;
}
int main()
{
linklist l;
createList_L(l);
displayList_L(l);
Elemtype e;
listDelete_L_i(l,3,e);
displayList_L(l);

    return 0;
}

练习题,不调用函数

//1.删除单链表l中的重复结点
int deleteDupNode(linklist &l){
linklist p=l->next,q=p,k;
if (!p) 
return 0;//空链直接返回
while (p->next){
while (q->next){
if (q->next->data==p->data){
k=q->next;
q->next=k->next;
free(k);
}
else 
q=q->next;
}
p=p->next;
q=p;
}

return 1;
}
//2.逆置单链表l
void flipL(linklist &l){
linklist p=l->next,q=p;
l->next=NULL;//分离头结点
while (p){
p=p->next;//q指向当前断链的头结点,p指向待分离链的头结点
q->next=l->next;
l->next=q;
q=p;
}
}
//3.非递增单链表ab,融合成非递增有序单链表c
linklist unionL(linklist &a,linklist &b){
linklist c=a;
linklist pa=a->next,pb=b->next,pc=c;
while (pa&&pb){
if (pa->data > pb->data){
pc->next=pb;
pc=pc->next;//pc始终指向C链的尾
pb=pb->next;
}
else {
pc->next=pa;
pc=pc->next;//pc始终指向C链的尾
pa=pa->next;
}
}
if(pa){
pc->next=pa;
}
if(pb){
pc->next=pb;
}
//pc->next=pa?pa:pb;
free(b);
return c;
}
//5.对不带头结点的L就地逆置
void createList_Lnohead(linklist &l){
l=NULL;
linklist p,q;
int x;
scanf ("%d",&x);
while (x!=-999){
q=(linklist)malloc(sizeof(node));
q->data=x;
if (!l){
p=q;l=q;
}else{
p->next=q;
q->next=NULL;
p=q;
}
scanf ("%d",&x);
}
}
void displayList_Lnohead(linklist &l){
linklist p=l;
while (p!=NULL){
printf ("%d ",p->data);
p=p->next;
}
printf ("\n");
}
void flip_Lnohead(linklist &l){
linklist p,q;
q=p=l;//可以连续赋值,从左到右
l=NULL;//分离头指针
while (p){
p=q->next;
q->next=l;
l=q;
q=p;
}
}
//6.对单链表l进行排序
// 冒泡for 
void sort_Lfor(linklist &l){
    linklist p,q;
    p=l->next;q=p->next;
    int t;
for (int i=0;i<listLength(l)-1;i++){
for (int j=0;j<listLength(l)-1-i;j++){
if (p->data >q->data){
t=p->data;
p->data=q->data;
q->data=t;
}
p=p->next;
q=q->next;
}
p=l->next;
q=p->next;
}
}
//7.单链表la,lb存储两个字符串,找出la中第一个不在lb中出现的字符
int haha(linklist &la,linklist &lb){
linklist pa=la->next;
int locate_L(linklist &l,linklist p);
while (pa){
if (locate_L(lb,pa))
pa=pa->next;
else
return pa->data;
}
}
int locate_L(linklist &l,linklist p){
linklist q=l->next;
while (q){
if (q->data==p->data)
return 1;
q=q->next;
}
return 0;
}
//8.递增有序la,lb,求交集lc
linklist jiaoji(linklist &la,linklist &lb){
linklist pa=la->next,pb=lb->next,lc,pc;
lc=(linklist )malloc(sizeof(node));lc->next=NULL;
pc=lc;
while (pa&&pb){
//如果两个元素相等则连接到lc上,否则比较大小后后移较小元素
if (pa->data > pb->data)
pb=pb->next;
if (pa->data < pb->data)
pa=pa->next;
if (pa->data==pb->data){
pc=(linklist )malloc (sizeof(node));
pc->data=pa->data;
pc->next=lc->next;
lc->next=pc;
pa=pa->next;pb=pb->next;
}
}
return lc;
}

//9.两个字符串la/lb,判断lb是否是la的子串(一个字符串中若干的字符称为子串)
int haha(linklist &la,linklist &lb){
linklist pa=la->next,pb=lb->next;
while (pa&&pa->data!=pb->data) pa=pa->next;
if (!pa) {
printf ("no\n");
return 0;
}
while (pb&&pa->data==pb->data){
 pb=pb->next;pa=pa->next;
}
if (!pb)printf ("yes\n");
else printf ("no\n");
return 1;
}

这里写图片描述

//10.
int DeleteandInsert(linklist &la,linklist &lb,int i,int j,int len){
if (i<0||j<0||len<0) return 0;
linklist p=la,q,s,t;
s=lb;
int k=0;
while (k<i&&p){
p=p->next;k++;
}//P指向第I个元素
if (!p) return 0;
q=p;
k=0;
while(k<len&&q){
q=q->next;k++;
}//q指向被删除的最后一个元素
if (!q) return 0;
k=0;
while(k<j-1&&s){
s=s->next;k++;
}//s指向被插入元素的前驱
if (!s) return 0;
t=s->next;
s->next=p->next;
p->next=q->next;
q->next=t;
return 1;
}
//11.删除单调递增链表l中所有值大于min并且小于max的元素(如果存在这样的元素的话)
//同时删除被删结点空间
void deletel(linklist &l,int min,int max){
linklist p=l,q;
while (p->next){
if (p->next->data>min&&p->next->data < max){
q=p->next;
p->next=q->next;
free(q);
}else
p=p->next;
if (!p)
break;
}
}

方法二:

int deletel(linklist &l,int min,int max){
linklist p=l,q;
while (p->next->data<=min&&p) p=p->next;
//找到第一个被删除结点的前驱
if (!p) return 0;
q=p->next;
while (q&&q->data<max) q=q->next;
//这里q&&q->data与q->Data&&q不同,后者会报错,因为当Q指向NULL时
//q->Data为错误的表达式
//q指向第一个不被删除的元素
p->next=q;
return 1;
}
//12.删除递增表L中所有值相同的多余元素
void deletel(linklist &l){
linklist p=l->next,q=p->next;
while (q){
if (p->data==q->data){
p->next=q->next;
free(q);
q=p->next;
}else {
p=p->next;
q=q->next;
}
}
}

这里写图片描述

void mergeAandB(linklist &la,linklist &lb,linklist &lc){
linklist pa=la->next,pb=lb->next;
linklist qa=pa->next,qb=pb->next;
lc=la;
while (qa&&qb){
pa->next=pb;
pb->next=qa;
pa=qa;
pb=qb;
qa=pa->next;
qb=pb->next;
}
if (!qa){
pa->next=pb;
}
if (!qb){
pb->next=pa;
}
}

这里写图片描述

//分析:本算法的思想是,按从小到大的顺序依次把A和B的元素
//插入新表的头部pc处,最后处理A或B的剩余元素.
void reverse_merge(linklist &la,linklist &lb,linklist &lc){
linklist pa=la->next,pb=lb->next,pc,t;
pc=NULL;
while (pa&&pb){
if (pa->data < pb->data ){
t=pa->next;
pa->next=pc;
pc=pa;
pa=t;
}
else {
t=pb->next;
pb->next=pc;
pc=pb;
pb=t;
}
}
while (pb){
t=pb->next;
pb->next=pc;
pc=pb;
pb=t;
}
while (pa){
t=pa->next;
pa->next=pc;
pc=pa;
pa=t;
}
lc=la;
lc->next=pc;
free(pb);

}
//8.递增有序la,lb,求交集lc
linklist jiaoji(linklist &la,linklist &lb){
linklist pa=la->next,pb=lb->next,lc,pc;
lc=(linklist )malloc(sizeof(node));lc->next=NULL;
pc=lc;
while (pa&&pb){
//如果两个元素相等则连接到lc上,否则比较大小后后移较小元素
if (pa->data > pb->data)
pb=pb->next;
else
if (pa->data < pb->data)
pa=pa->next;
else{
if (pc->data!=pa->data){
pc=(linklist )malloc (sizeof(node));
pc->data=pa->data;
pc->next=lc->next;
lc->next=pc;
}
pa=pa->next;pb=pb->next;
}

}
return lc;
}
//2.30 对于A,删去即在b又在c中出现的元素
void lalblc(linklist &la,linklist &lb,linklist &lc){
linklist pa=la,pb=lb->next,pc=lc->next,t;
while (pa->next&&pb&&pc){
if (pb->data > pc->data)
pb=pb->next;
else
if (pb->data < pc->data)
pc=pc->next;
else
{
    if (pa->next->data < pb->data)
    pa=pa->next;
    else{
    while (pa->next->data == pb->data)
    {
    t=pa->next;
    pa->next=t->next;
    free(t);
    }
    pb=pb->next;pc=pc->next;
}
}
}
}

//思路:
1.对b和c进行比较:不等时较小数后移;相等时再对a进行比较:a小时移动a,a大时bc移动,相等时对a进行删除。注意这里用while判断pa->next->data == pb->data,因为a中可能有重复的被删除元素。

2)

2.30 
void LinkList_Intersect_Delete(LinkList &A,LinkList B,LinkList C)//在链表结构上重做上题
{
  p=B->next;q=C->next;r=A-next;
  while(p&&q&&r)
  {
    if(p->data<q->data) p=p->next;
    else if(p->data>q->data) q=q->next;
    else
    {
      u=p->data; //确定待删除元素u
      while(r->next->data<u) r=r->next; //确定最后一个小于u的元素指针r
      if(r->next->data==u)
      {
        s=r->next;
        while(s->data==u)
        {
          t=s;s=s->next;free(t); //确定第一个大于u的元素指针s
        }//while
        r->next=s; //删除r和s之间的元素
      }//if
      while(p->data=u) p=p->next;
      while(q->data=u) q=q->next;
    }//else
  }//while
}//LinkList_Intersect_Delete 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值