数据结构笔记(线性表~队列)


一, 线性表

1,顺序表

1.1,顺序存储表示

l o c ( a i ) = l o c ( a 1 ) + ( i − 1 ) ∗ l loc(ai)=loc(a1)+(i-1)*l loc(ai)=loc(a1)+(i1)l

顺序存储结构是一种随机存取的存储结构。

1.2,顺序表的初始化

typedef struct
{
	int *elem;//存储空间的基地址
	int length;
}sqlist;
int init(sqlist &l)
{
	l.elem=new int[100];
	if(!l.elem)exit(1);
	l.length=0;
	return 0;
}

1.3,顺序表的取值

int getelem(sqlist &l,int i,int &e)//i是位置 e是要返回的媒介
{
	if(i<1||i>l.length) return error;
	e=l.elem[i-1];//因为下标0开始  所以i-1
	return ok;
}

1,4 顺序表的查找

int find(sqlist &l int e)//e:要寻找的值
{
	for(int i=0;i<l.length;i++)
	{
		if(l.elem[i]==e) return i+1;//查找成功,返回i+1
	}
	return 0;//查找失败 
}

1.5 顺序表的插入

从下标为i-1 整体往后移,再把插入的e 放到下标为i-1的位置 ,长度再+1。

int inserts(sqlist &l,int i,int e)
{
	if(i<1||i>l.length+1) return error;//i不合法
	if(l.length==maxsize) return error;//空间满
	for(int j=l.length-1;j>=i-1;i--)
	{
		l.elem[j+1]=l.elem[j];
	}
	l.elem[i-1]=e;
	l.length++;
	return ok;
}

1.6 顺序表的删除

int erases(sqlist &l,int i)
{
	if(i<1||i>l.length+1) return error;//i不合法
	for(int j=i;j<=l.length-1;j++)
	{
		l.elem[j-1]=l.elem[j];
	}
	--l.length;
	return ok;
}

1.7 顺序表的元素逆置

void reverse(Sqlist &L) {
    int i, j, temp;
    for (i = 0, j = L.length - 1; i < j; ++i, --j) {
        // 头尾两两交换
        temp = L.data[i];
        L.data[i] = L.data[j];
        L.data[j] = temp;
    }
}

1.8 删除下标为i~j的数据元素

void deleteRange(Sqlist &L, int i, int j) {
    assert(0 <= i && 0 <= j && i < L.length && j < L.length);
    // 用j+1后面的元素去覆盖往前数第j-i+1个元素
    int delta = j - i + 1;
    for (int k = j+1; k < L.length; ++k) {
        L.data[k-delta] = L.data[k];
    }
    L.length -= delta;
}

1.9 Partition操作

void partition(Sqlist &L) {
    assert(L.length != 0);
    int p = L.data[0];
    int i = 0, j = L.length-1;
    while (i < j) {
        while (i < j && L.data[j] > p) --j;
        if (i < j) {
            L.data[i] = L.data[j];
            ++i;
        }

        while (i < j && L.data[i] < p) ++i;
        if (i < j) {
            L.data[j] = L.data[i];
            --j;
        }
    }
    L.data[i] = p;
}

2 单链表

2.1单链表的初始化

#include <iostream>

#include <stdlib.h>

#define MAXSIZE 1000

#define OK 1

#define ERROR 0

#define Status int

#define OVERFLOW -2

#define ElemType string

using namespace std;

typedef struct LNode {

	ElemType data; //结点的数据域

	struct LNode *next; //结点的指针域

} LNode, *LinkList; //LinkList为指向结构体LNode的指针类型

Status InitList(LinkList &L)
{
	L=new LNode;
	L->next=NULL;
	return 0;
 } 

2.2单链表的取值

Status GetElem(LinkList L, int i, ElemType &e)
{
	LNode *p;
	int j=1;//计算器j 
	p=L->next;//p指向首元结点
	while(p&&(j<i))//直至p为空或者 p指向第i个元素
	{
		p=p->next;j++;
	}
	
	if(!p||(j>i))return -1;
	
	e=p->data;//取出第i个元素
	return 0;
}

2.3单链表的按值查找

LinkList LocateElem(LinkList L, ElemType &e)
{
	LNode *p;
	p=L->next;
	while(p&&(p->data!=e))p=p->next;
	return p;//返回地址p
}

2.4单链表的插入

Status ListInsert(LinkList &L, int i, ElemType e)
{
	LNode *p;
	LNode *s;//s为要插入的元素
	p=L;
	int j=1;
	while(p&&(j<i))//让p指向第i-1个元素 且防止p为空
	{
		p=p->next;j++;
	}
   s = new LNode;
   s->data=e;
   //-----------------
   s-> next=p->next;
   p->next=s;
   //------------------
   return 0; 
}

2.5单链表的删除

Status ListDelete(LinkList &L, int i)
{
	LNode *p,*q;
	p=L; 
	int j=1;
	while((p->next)&&(j<i))//让p指向第i-1个元素 ,(p->next)含义是 最坏情况 p->next=Null指向最后一个元素。删除不扑空。
	{
		p=p->next;j++;
	}
	
	q=new LNode;//q用来接力 使p指向下下一个元素
	//---------------
	q=p->next;
	p->next=q->next;
    //----------------
     delete q;
	return 0;
	
}

2.6 单链表的创建

2.6.1 头插法
void CreateList_H(LinkList &L, int n)
{
	LNode *p;
	L=new LNode;
	L->next=NULL;
	for(int i=0;i<n;i++) 
	{
		p=new LNode;
		cin>>p->data;
        //-------------
		p->next=L->next;
		L->next=p;
	   //--------------
    }
}
2.6.1 尾插法
void createlistR(LNode *&list,  int n) {
    LNode *s, *r; // s用来指向新申请的节点,r **始终** 指向list的终端节点
    int i;
    list =new LNode;
    list->next = NULL;
    r = list;
    for (int i = 0; i < n; i++) {
        s = new LNode;
        cin>>s->data ;
         s->next=NULL;
        //-----------------
        r->next = s;  // 让当前的终端节点指向新来的节点
        r = r->next;  // 更新r,让r指向新的终端节点
    }
    //r->next = NULL;

2.7 合并递增单链表

void mergeR(LNode *A, LNode *B, LNode *&C) {
    // 由于不能改变了A, B自己的内容,所以得设定p, q来进行操作
    LNode *p = A->next;
    LNode *q = B->next;

    LNode *r;  // r始终指向C的终端节点
    C = A;  // 将A的头结点用来做C的头结点
    C->next = NULL;
    //free(B);
    r = C;  // 初试的时候C也是终端节点
    while (p != NULL && q != NULL) {
        if (p->data <= q->data) {
            r->next = p; // 让当前的终端节点指向新的终端节点
            p = p->next; // p自然要往后挪一步
            r = r->next; // 更新r的指向,让r指向新的终端节点
        } else {
            r->next = q;
            q = q->next;
            r = r->next;
        }
    }

    // p还有剩余
    if (p != NULL) {
        r->next = p;
    }

    // q还有剩余
    if (q != NULL) {
        r->next = q;
    }
}

2.8 合并递减单链表

void mergeF(LNode *A, LNode *B, LNode *&C) {
    LNode *p = A->next;
    LNode *q = B->next;
    LNode *s;
    C = A;
    C->next = NULL;
    free(B);
    while (p != NULL && q != NULL) {
        if (p->data <= q->data) {
            // 这里就体现出s的作用了
            // 如果没有s,
            // 则直接p->next = C->next, 
            // 那么改变了p的指向,p无法再往后挪了
            s = p;
            p = p->next;
            s->next = C->next;
            C->next = s;
        } else {
            s = q;
            q = q->next;
            q->next = C->next;
            C->next = s;
        }
    }

    // 由于头插,所以这里必须循环将每个剩余元素放到链表C的前面去
    while (p != NULL) {
        s = p;
        p = p->next;
        s->next = C->next;
        C->next = s;
    }

    while (q != NULL) {
        s = q;
        q = q->next;
        s->next = C->next;
        C->next = s;
    }
}

** 线性表的总结** (重点)

地址公式
a i = a 1 + ( i − 1 ) ∗ l a_i=a_1+(i-1)*l ai=a1+(i1)l
顺序表の 平均移动次数:

插入:
E i n s e r t = n 2 E_insert=\frac{n}{2} Einsert=2n
删除:
E d e l e t e = n − 1 2 E_delete=\frac{n-1}{2} Edelete=2n1

顺序表の 移动元素的个数:

插入:
n − i + 1 n-i+1 ni+1
删除:
n − i n-i ni

二, 栈与队列

1,顺序栈

typedef struct SqStack{
    
    
    int data[maxSize];
    int top;
} SqStack;

void initStack(SqStack &st) {
    
    
    st.top = -1;
}

int isEmpty(SqStack st) {
    
    
    return st.top == -1;
}

int push(SqStack &st, int x) {
    
    
    if (st.top == maxSize) return 0;
    st.data[++st.top] = x;
    return 1;
}

int pop(SqStack &st, int &x) {
    
    
    if (st.top == -1) return 0;
    x = st.data[st.top--];
    return 1;
}

//------------考试中顺序栈用法的简洁写法------------------

int stack[maxSize]; int top = -1;  // 这两句话连定义带初始化都有了                                              
stack[++top] = x;  // 一句话实现进栈                   -
x = stack[top--];  // 一句话实现出栈                   -


//----------------------------------------------------

2,链栈

头插头删
注:要不要头结点都可以。

typedef struct LNode{
    
    
    int data;
    struct LNode *next;
} LNode;

void initStack(LNode *&lst) {
    
    
    lst = (LNode*)malloc(sizeof(LNode));
    lst->next = NULL;  // 还是老规矩:申请新的节点后一定要为其指针域设置为空
}

int isEmpty(LNode *lst) {
    
    
    return lst->next == NULL;
}


void push(LNode *lst, int x) {
    
    
    // 步骤一:申请新的节点,存放x的值
    // 步骤二:头插法将新的节点插入链栈中
    
    LNode *p = (LNode*)malloc(sizeof(LNode));
    p->data = x;
    
    //----------------
    p->next = NULL;
    p->next = lst->next;
    lst->next = p;
}

int pop(LNode *lst, int &x) {
    
    
    // 步骤一:判空
    // 步骤二:删除节点

    if (lst->next == NULL) return 0;

    x = lst->data;
    LNode *p;
    
  //------------------------
     p = lst->next;
    lst->next = lst->next->next;
    free(p);
    return 1;
}


int gettop(lnode *s){
    
    

if(s!=null)
return s->data;
}

3,顺序队列

typedef struct {
    
    
    int data[maxSize];
    int front;  // 队首指针
    int rear;  // 队尾指针
}SqQueue;

void initQueue(SqQueue &qu) {
    
    
    qu.front = qu.rear = 0;  // 队首和队尾指针重合,并且指向0
}
void initQueue(SqQueue &qu) {
    
    
    qu.front = qu.rear = 0;  // 队首和队尾指针重合,并且指向0
}

int inQueue(SqQueue &qu, int x) {
    
    
    if ((qu.rear+1)%maxSize == qu.front) return 0;  // 队满则不能入队
    qu.rear = (qu.rear+1)%maxSize;  // 若未满,则先移动指针
    qu.data[qu.rear] = x;  // 再放入元素
    return 1;
}

int deQueue(SqQueue &qu, int &x) {
    
    
    if (qu.front == qu.rear)  return 0;  // 若队空,则不能删除
    qu.front = (qu.front+1)%maxSize;  // 若队不空,则先移动指针
    x = qu.data[qu.front];  // 再取出元素
    return 1;
}

3,链队

typedef struct QNode {
    
    
    int data;  // 数据域
    struct QNode *next;   // 指针域
}QNode;

typedef struct {
    
    
    QNode *front;  // 队头指针
    QNode *rear;  // 队尾指针
}LiQueue;


void init_Queue(LiQueue *&lqu) {
    
    
    lqu = (LiQueue*)malloc(sizeof(LiQueue));
    lqu->front = lqu->rear = nullptr;
}

int isQueue_Empty(LiQueue *lqu) {
    
    
    return (lqu->rear == nullptr || lqu->front == nullptr);  // 注意有两个
}

void enQueue(LiQueue *lqu, int x) {
    
    
    QNode *p;
    p = (QNode*)malloc(sizeof(QNode));
    p->data = x;
    p->next = nullptr;
    if (lqu->rear == nullptr) {
    
      // 若队列为空,则新结点是队首结点,也是队尾结点
        lqu->front = lqu->rear = p;
    } else {
    
    
        lqu->rear->next = p;  // 将新结点链接到队尾,rear指向它
        lqu->rear = p;
    }
}

int deQueue(LiQueue *lqu, int &x) {
    
    
    QNode *p;
    if (lqu->rear == nullptr) {
    
      // 队空不能出队
        return 0;
    } else {
    
    
        p = lqu->front;
    }
    if (lqu->front == lqu->rear) {
    
      // 队列中只有一个结点时的出队操作需要特殊处理
        lqu->front = lqu->rear = nullptr;
    } else {
    
    
        lqu->front = lqu->front->next;
    }
    x = p->data;
    free(p);
    return 1;
}

猜你喜欢

转载自blog.csdn.net/weixin_46339668/article/details/112986551